如何使用带有强制转换的泛型参数(限制为整数类型)实现方法?

时间:2019-03-02 21:47:48

标签: c# generics types casting

我基本上希望它可以编译:

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

类型T将是System.UInt32System.UInt64中的一种(但可能更多)。

还是我必须分别实现每种类型的ISqrtN(超载)?

3 个答案:

答案 0 :(得分:2)

C#不支持通用数字。没有通用的数字基类型,也没有接口声明基本的数字运算。最简单的方法是让用户超载

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

然后,IntelliSense将显式显示允许的参数类型。例如,Math类就是为AbsMax做的。

答案 1 :(得分:1)

重载解析在编译时执行,即使对于通用方法也是如此。首选的解决方案是根本不使用通用方法,因为您不能将enter code here 限制为可以防止人们调用T等的类型。

维护通用方法签名的变通办法是使用ISqrtN<DateTime>运行时绑定:

dynamic

或手动进行类型检查并强制转换为特定的受支持类型:

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

由于C#不允许直接从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)进行强制转换,因此需要进行中间T强制转换,但它们在运行时不会有所不同。

答案 2 :(得分:0)

您将不得不分别实现它们。最好的办法是对值类型where T : struct使用泛型类型约束,但这将允许发送任何结构。 如果您确实想对uintulong施加约束,我建议您将原始实现保留为私有方法,并仅创建其他2个公共方法,每个公共方法都针对您要支持的类型,并且让他们调用私有方法。