I want to write generic class which should work with byte
and ushort
types. What constraint should I use for this class? How can I detect MaxValue
property inside of this class?
class MyClass<T> // where T: ???
{
void Foo()
{
int maxValue = T.MaxValue; // how can I do this?
}
}
If class was created with unexpected type, which doesn't contain MaxValue property, I don't care - for example, I can throw exception at runtime.
One way would be to leverage the new dynamic
keyword:
void Main()
{
Test(10);
Test(10.234);
Test((Byte)42);
Test(true);
}
public void Test<T>(T value)
where T : struct
{
T maxValue = MaxValue((dynamic)value);
maxValue.Dump();
}
public int MaxValue(int dummy)
{
return int.MaxValue;
}
public double MaxValue(double dummy)
{
return double.MaxValue;
}
public byte MaxValue(byte dummy)
{
return byte.MaxValue;
}
public object MaxValue(object dummy)
{
// This method will catch all types that has no specific method
throw new NotSupportedException(dummy.GetType().Name);
}
Or, you could use reflection to obtain the MaxValue field:
void Main()
{
Test(10);
Test(10.234);
Test((Byte)42);
Test(true);
}
public void Test<T>(T value)
where T : struct
{
FieldInfo maxValueField = typeof(T).GetField("MaxValue", BindingFlags.Public
| BindingFlags.Static);
if (maxValueField == null)
throw new NotSupportedException(typeof(T).Name);
T maxValue = (T)maxValueField.GetValue(null);
maxValue.Dump();
}
You can test these two programs through LINQPad.
Try something like this
public T GetMaxValue()
{
object maxValue = default(T);
TypeCode typeCode = Type.GetTypeCode(typeof(T));
switch (typeCode)
{
case TypeCode.Byte:
maxValue = byte.MaxValue;
break;
case TypeCode.Char:
maxValue = char.MaxValue;
break;
case TypeCode.DateTime:
maxValue = DateTime.MaxValue;
break;
case TypeCode.Decimal:
maxValue = decimal.MaxValue;
break;
case TypeCode.Double:
maxValue = decimal.MaxValue;
break;
case TypeCode.Int16:
maxValue = short.MaxValue;
break;
case TypeCode.Int32:
maxValue = int.MaxValue;
break;
case TypeCode.Int64:
maxValue = long.MaxValue;
break;
case TypeCode.SByte:
maxValue = sbyte.MaxValue;
break;
case TypeCode.Single:
maxValue = float.MaxValue;
break;
case TypeCode.UInt16:
maxValue = ushort.MaxValue;
break;
case TypeCode.UInt32:
maxValue = uint.MaxValue;
break;
case TypeCode.UInt64:
maxValue = ulong.MaxValue;
break;
default:
maxValue = default(T);//set default value
break;
}
return (T)maxValue;
}
You can only use struct
as a constraint which will only allow value types for T
. Every specific value type as a constraint will be rejected by the compiler. So you have to do a runtime check whether T
is one of your allowed types.
The only way to get the MaxValue
of your (unknown) type T
is reflection with something like this:
typeof(T).GetField("MaxValue").GetValue(null);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With