简体   繁体   English

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

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

I basically want this to compile: 我基本上希望它可以编译:

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

The type T will be one of System.UInt32 , System.UInt64 (but possibly more). 类型T将是System.UInt32System.UInt64 (但可能更多)。

Or will I have to implement each type of ISqrtN separately (overloading)? 还是我必须分别实现每种ISqrtN类型(重载)?

C# has no support for generic numerics. C#不支持通用数字。 There is no common numeric base type and there is no interface declaring the basic numeric operations. 没有通用的数字基类型,也没有接口声明基本的数字运算。 The easiest way to go, is to user overloads 最简单的方法是避免用户超载

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

Then IntelliSense will show you the allowed parameter types explicitly. 然后,IntelliSense将显式显示允许的参数类型。 This is what the Math class does for the Abs or Max for example. 例如,这就是Math类对AbsMax的作用。

Overload resolution is performed at compile time, even for generic methods. 重载解析是在编译时执行的,即使对于通用方法也是如此。 The preferred solution would be to not use a generic method here at all, since you can't constrain T to types that work to prevent people from calling ISqrtN<DateTime> etc. 首选的解决方案是根本不使用通用方法,因为您不能将T限制为可以防止人们调用ISqrtN<DateTime>等的类型。

Workarounds that maintain the generic method signature are either using dynamic runtime binding: 维护通用方法签名的解决方法是使用dynamic运行时绑定:

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

or manually type-checking and casting to specific supported types: 或手动类型检查并转换为特定的受支持类型:

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();
}

The intermediate (object) casts are required because C# won't allow a direct cast from T to uint , but they won't make a difference at runtime. 要求进行中间(object)强制转换,因为C#不允许从T直接转换为uint ,但是它们在运行时不会有所作为。

You would have to implement them separately. 您将不得不分别实现它们。 The best you could do is to use a generic type constraint to a value type where T : struct but this would allow any struct to be sent. 最好的办法是对where T : struct的值类型使用通用类型约束,但这将允许发送任何结构。 If you really want to have that constraint on uint and ulong I would recommend keeping your original implementation as a private method and just create other 2 public methods, each one for the type you want to support, and make them call the private method. 如果您确实希望对uintulong施加约束,那么我建议您将原始实现保留为私有方法,并仅创建其他2个公共方法,每个公共方法针对您要支持的类型,然后将它们称为私有方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我不能将&#39;as&#39;用于限制为接口的泛型类型参数? - Why can't I use 'as' with generic type parameter that is constrained to be an interface? 将不受约束的泛型类型参数传递给受约束的方法 - Passing unconstrained generic type parameter to a constrained method 如何在扩展方法中获取&#39;this&#39;参数的泛型类型参数? - How can I get the generic type parameter of the 'this' parameter in an extension method? 为什么我必须强制转换为类型参数,而不能使用受约束的类型? - Why do I have to cast to type parameter and can't use the constrained type? 约束通用类型参数的继承 - Inheritance on a constrained generic type parameter 为什么我不能将对象强制转换为约束泛型? - Why can't I cast an object to a constrained generic? 为什么不能将一个受约束的开放泛型类型转换为受约束类型? - Why can't you cast a constrained open generic typed to the constrained type? 如何将对象转换为C ++ / CLI中不知道其类型参数的通用列表? - How can I cast an Object to a generic List I don't know the type parameter of in C++/CLI? 类型约束C#Generic的无效转换 - Invalid Cast of Type Constrained C# Generic 如何使用受约束的泛型类型参数将 class 实例化为派生接口 - How to instantiate a class as the interface that it derives from with constrained generic type parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM