簡體   English   中英

如何使用帶有強制轉換的泛型參數(限制為整數類型)實現方法?

[英]How can I implement a method with a generic parameter (constrained to an integer type) with a cast?

我基本上希望它可以編譯:

T ISqrtN<T>(T N) => (T)Math.Sqrt((double)N);

類型T將是System.UInt32System.UInt64 (但可能更多)。

還是我必須分別實現每種ISqrtN類型(重載)?

C#不支持通用數字。 沒有通用的數字基類型,也沒有接口聲明基本的數字運算。 最簡單的方法是避免用戶超載

uint ISqrtN(uint N) => (uint)Math.Sqrt((double)N);
ulong ISqrtN(ulong N) => (ulong)Math.Sqrt((double)N);

然后,IntelliSense將顯式顯示允許的參數類型。 例如,這就是Math類對AbsMax的作用。

重載解析是在編譯時執行的,即使對於通用方法也是如此。 首選的解決方案是根本不使用通用方法,因為您不能將T限制為可以防止人們調用ISqrtN<DateTime>等的類型。

維護通用方法簽名的解決方法是使用dynamic運行時綁定:

T ISqrtN<T>(T N) => (T)Math.Sqrt((dynamic)N);

或手動類型檢查並轉換為特定的受支持類型:

T ISqrtN<T>(T N)
{
    if (typeof(T) == typeof(uint))
        return (T)(object)(uint)Math.Sqrt((uint)(object)N);
    else if (typeof(T) == typeof(ulong))
        return (T)(object)(ulong)Math.Sqrt((ulong)(object)N);
    else
        throw new ArgumentException();
}

要求進行中間(object)強制轉換,因為C#不允許從T直接轉換為uint ,但是它們在運行時不會有所作為。

您將不得不分別實現它們。 最好的辦法是對where T : struct的值類型使用通用類型約束,但這將允許發送任何結構。 如果您確實希望對uintulong施加約束,那么我建議您將原始實現保留為私有方法,並僅創建其他2個公共方法,每個公共方法針對您要支持的類型,然后將它們稱為私有方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM