我想编写应该使用byte
和ushort
类型的通用类。我应该对这个类使用什么约束?如何检测MaxValue
此类内部的属性?
class MyClass<T> // where T: ???
{
void Foo()
{
int maxValue = T.MaxValue; // how can I do this?
}
}
如果类是用不包含 MaxValue 属性的意外类型创建的,我不在乎 - 例如,我可以在运行时抛出异常。
我想编写应该使用byte
和ushort
类型的通用类。我应该对这个类使用什么约束?如何检测MaxValue
此类内部的属性?
class MyClass<T> // where T: ???
{
void Foo()
{
int maxValue = T.MaxValue; // how can I do this?
}
}
如果类是用不包含 MaxValue 属性的意外类型创建的,我不在乎 - 例如,我可以在运行时抛出异常。
一种方法是利用 newdynamic
关键字:
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);
}
或者,您可以使用反射来获取 MaxValue 字段:
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();
}
您可以通过LINQPad测试这两个程序。
尝试这样的事情
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;
}
您只能将struct
其用作仅允许T
. 作为约束的每个特定值类型都将被编译器拒绝。所以你必须做一个运行时检查是否T
是你允许的类型之一。
MaxValue
获得您的(未知)类型的唯一方法T
是反射,如下所示:
typeof(T).GetField("MaxValue").GetValue(null);
该约束在 C# 中是不可能的。您可以使用特定接口限制值类型,例如
where T : struct, IComparable, IFormattable,
IConvertible, IComparable<T>, IEquatable<T>
不幸的是,这将匹配比您想要的更多的类型。并且MaxValue
不是任何接口的成员(它是一个字段!),所以约束在这里对你没有帮助。您可能想在fero的回答中使用反射。
好吧,这没有任何限制,正如我从这里和我读过的其他一些地方得出的结论。
但是,您可以使用接口包装 ushort 和 byte:
public interface IReturnUShortAndBytes
{
ushort ReturnUShortsOrZero();
byte ReturnByteOrZero();
}
这不是最好的事情,但它可能会起作用,这取决于你需要什么