What do you mean is a very bad idea, to have this 'OR' constraint? I don't think so. Take a look at this example: Lets say you want to add an extention to the values types short, int, long.
public static class ValueTypeExtention
{
// A
public static ulong ToUnsignedLongUnchecked(this T signedValue) where T : IConvertible
{
return signedValue.ToUInt64();
}
// B
public static ulong ToUnsignedLongUnchecked(this T signedValue) where T : struct { ... }
// C
public static ulong ToUnsignedLongUnchecked(this short signedValue) { return signedValue.ToUInt64(); }
public static ulong ToUnsignedLongUnchecked(this int signedValue) { return signedValue.ToUInt64(); }
public static ulong ToUnsignedLongUnchecked(this long signedValue) { return signedValue.ToUInt64(); }
// D
public static ulong ToUnsignedLongUnchecked(this T signedValue) where T : short | int | long
{
return unchecked((ulong)signedValue);
}
// E
public static ulong ToUnsignedLongUnchecked(this T signedValue) where T : (short | int | long) as IConvertible
{
return signedValue.ToUInt64();
}
}
A, B and C are versions how you could solve this problem nowadays. But lets have a deeper look: - A allows bool bValue=false; ulong ulVal = bValue.ToUnsignedLongUnchecked();. It allows it for every class/struct that implements IConvertible. - B needs type checking and offers ToUnsignedLongUnchecked() to every struct even BITMAPINFO. - C is the only way to solve the condition completely but needs multiple implementations. Using where T : struct, IConvertible as constraints is the best way to solve this problem with generics so far. The 'pseudo' constraint D just allows T to be one of this 3 value types. And I think E could be the best way.
Greetings Covean