如何在C#中求和泛型数
本文关键字:求和 泛型 | 更新日期: 2023-09-27 18:24:58
可能重复:
仅适用于整数的C#通用约束
正如您在下面的代码中看到的,我需要计算两个泛型数字的和。
public class NumberContainer<T>
{
public T ValueA { get; private set; }
public T ValueB { get; private set; }
public T Total { get { return ValueA + ValueB; } }
}
然而,不可能将两个t值直接相加,这会导致以下编译器错误:
运算符"+"不能应用于类型为"T"answers"T"的操作数
既然我不打算将t用于表示数字的值类型(short、ushort、int、uint等)之外的任何其他类型,我该如何执行求和?(效率是一个需要考虑的因素)
您可以使用LINQ的"小魔法":
private static readonly Func<T, T, T> adder;
static NumberContainer() {
var p1 = Expression.Parameter(typeof (T));
var p2 = Expression.Parameter(typeof (T));
adder = (Func<T, T, T>)Expression
.Lambda(Expression.Add(p1, p2), p1, p2)
.Compile();
}
public T Total { get { return adder(ValueA, ValueB); } }
唯一的缺点是,即使NumberContainer
是用不支持加法的类型T
实例化的,此代码也将编译;当然,它会在运行时抛出一个异常。另一个好处是,此应与用户定义的+
运算符一起使用。
除了使用LINQ,如果您在.NET 4上,还可以使用dynamic
:
static T Add<T>(T x, T y)
{
dynamic dx = x, dy = y;
return dx + dy;
}
在您的代码示例中,这将变成:
public class NumberContainer<T> 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
是一个不支持+
的随机结构,那么最终会出现一个异常(我认为)。
您可以为T
指定一个约束,即它必须是一个结构,也许它实现了IConvertable,然后使用Convert
。
public class NumberContainer<T>
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));
}
}
}
然而,泛型无法保证T在编译时是整数或浮点类型。不过,您可以在运行时对其进行检查,然后抛出异常。
您可以将其视为一个抽象基类,并派生指定T值并为Total 提供实现的特定类
public abstract class NumberContainer<T>
where T: struct
{
public T ValueA { get; private set; }
public T ValueB { get; private set; }
public abstract T Total();
}
public class IntContainer : NumberContainer<int>
{
public override int Total()
{
return ValueA + ValueB;
}
}