如何在C#中汇总通用数字?

可能重复:
C#generics约束仅用于整数

正如您在下面的代码中看到的,我需要计算两个通用数字的总和。

public class NumberContainer { public T ValueA { get; private set; } public T ValueB { get; private set; } public T Total { get { return ValueA + ValueB; } } } 

但是,不可能直接添加两个T值,这会导致编译器错误如下:

运算符’+’不能应用于’T’和’T’类型的操作数

鉴于我不打算将T用于表示数字(short,ushort,int,uint等)的值类型以外的任何其他内容,我怎么能执行总和呢? (效率是一个需要考虑的因素)

你可以用LINQ的“小魔法”来做到这一点:

 private static readonly Func adder; static NumberContainer() { var p1 = Expression.Parameter(typeof (T)); var p2 = Expression.Parameter(typeof (T)); adder = (Func)Expression .Lambda(Expression.Add(p1, p2), p1, p2) .Compile(); } public T Total { get { return adder(ValueA, ValueB); } } 

唯一的缺点是,即使NumberContainer使用不支持添加的类型T实例化,此代码也会编译; 当然它会在运行时抛出exception。 另一个好处是,它应该与用户定义的+运算符一起使用。

除了使用LINQ之外,如果您使用的是.NET 4,则可以使用dynamic

 static T Add(T x, T y) { dynamic dx = x, dy = y; return dx + dy; } 

在您的代码示例中,这变为:

 public class NumberContainer where T: struct { public T ValueA { get; private set; } public T ValueB { get; private set; } public T Total { get { return ((dynamic)ValueA) + ((dynamic)ValueB); } } } 

但这种方法并不能确保安全。 如果T是一些不支持+随机结构,你最终会得到一个exception(我认为)。

您可以为T指定一个必须是结构的约束,并且可能它实现了IConvertable,然后使用Convert

 public class NumberContainer where T : struct, IConvertible { public T ValueA { get; private set; } public T ValueB { get; private set; } public T Total { get { // do type checking here, then: return (T)Convert.ChangeType( Convert.ToDouble((object)ValueA) + Convert.ToDouble((object)ValueB), typeof(T)); } } } 

但是,generics无法保证在编译时T是整数或浮点类型。 但是,您可以在运行时检查它,并抛出exception。

您可以将此视为抽象基类,并派生指定T值的特定类,并为Total提供实现

 public abstract class NumberContainer where T: struct { public T ValueA { get; private set; } public T ValueB { get; private set; } public abstract T Total(); } public class IntContainer : NumberContainer { public override int Total() { return ValueA + ValueB; } }