adyavanapalli
adyavanapalli

Reputation: 500

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).

Or will I have to implement each type of ISqrtN separately (overloading)?

Upvotes: 0

Views: 57

Answers (3)

kalimag
kalimag

Reputation: 1196

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.

Workarounds that maintain the generic method signature are either using dynamic runtime binding:

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.

Upvotes: 1

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112402

C# has no support for generic numerics. 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. This is what the Math class does for the Abs or Max for example.

Upvotes: 2

IPValverde
IPValverde

Reputation: 2029

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. 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.

Upvotes: 0

Related Questions