C#添加两个通用值
有人可以解释为什么这不起作用吗? 我试图能够添加两个值,无论数字types。
public static T Add<T> (T number1, T number2) { return number1 + number2; }
当我编译这个,我得到以下错误:
Operator '+' cannot be applied to operands of type 'T' and 'T'
没有通用的约束,允许您强制执行运算符重载。 你可以看看下面的库 。 另外,如果您使用.NET 4.0,则可以使用dynamic
关键字:
public static T Add<T>(T number1, T number2) { dynamic a = number1; dynamic b = number2; return a + b; }
显然,这不适用于generics所要求的编译时安全性。 应用编译时安全的唯一方法是强制通用约束。 而对于你的情况,没有可用的限制。 欺骗编译器只是一个骗术。 如果Add方法的调用方不传递与+运算符一起工作的types,则代码将在运行时抛出exception。
这里给出的解决scheme运作良好,但我想我会添加另一个使用expression式
public static T Add<T>(T a, T b) { // Declare the parameters var paramA = Expression.Parameter(typeof(T), "a"); var paramB = Expression.Parameter(typeof(T), "b"); // Add the parameters together BinaryExpression body = Expression.Add(paramA, paramB); // Compile it Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile(); // Call it return add(a, b); }
这样你就创build了一个执行加法的Func<T, T, T>
。 完整的解释可以在这篇文章中find。
typesT不是编译器已知的,所以它找不到在任何地方定义的重载+运算符…
你现在可以做的最好的是声明你的方法(因为所有的数字types都可以转换为double):
public static double Add (double number1, double number2) { return number1 + number2; }
或者如果你确定一个合适的+操作符将被定义:
public static T Add<T>(T number1, T number2) { dynamic dynamic1 = number1; dynamic dynamic2 = number2; return dynamic1 + dynamic2; }
更新
或两者的组合:
public static T Add<T>(T in1, T in2) { var d1 = Convert.ToDouble(in1); var d2 = Convert.ToDouble(in2); return (T)(dynamic)(d1 + d2); }
当我想要一个可以在任意数字列表上工作的generics方法时,这是一个问题,例如:
public T Calculate<T>(IEnumerable<T> numbers);
我find的解决scheme是使用lambdaexpression式:
public T Calculate<T>(Func<T, T, T> add, IEnumerable<T> numbers);
然后你会打电话给你
var sum = this.Calculate((a, b) => a + b, someListOfNumbers);
很显然,在某些情况下,你可能只是在代码里面加上+而不是lambdaexpression式,但是如果你需要用通用的方式来执行math运算,这是我能想到的最简单的事情,那就是编译安全。
Since this is generic type without a constraint compiler has no knowledge if the types involved will have '+' overloaded hence the compiler error These are some workarounds public static TResult Add<T1, T2, TResult>(T1 left, T2 right, Func<T1, T2, TResult> AddMethod) { return AddMethod(left, right); } var finalLabel = Add("something", 3,(a,b) => a + b.ToString()); Below code could let you build same but evaluated at run time so not run time safe public static T AddExpression<T>(T left, T right) { ParameterExpression leftOperand = Expression.Parameter(typeof(T), "left"); ParameterExpression rightOperand = Expression.Parameter(typeof(T), "right"); BinaryExpression body = Expression.Add(leftOperand, rightOperand); Expression<Func<T, T, T>> adder = Expression.Lambda<Func<T, T, T>>( body, leftOperand, rightOperand); Func<T, T, T> theDelegate = adder.Compile(); return theDelegate(left, right); }
public class generic<T> { T result; public generic(T eval1, T eval2) { dynamic a = eval1; dynamic b = eval2; result = a + b; Console.WriteLine(result); Console.ReadLine(); }
static void Main(string[] args) { generic<int> genobj = new generic<int>(20,30); }
这可以防止开发人员编写错误的代码。 很less有问题可以更好地解释这个问题:
1>编译器是否知道types[不,因为它是genericstypes]。 2>它可以接受对象作为参数[是的,它可以,因此它不会知道如何处理它们 – >多function代码]
既然,你想防止你的代码变成bug,C#不允许你有'+'''和其他操作符。
解决scheme:如果需要,可以使用“dynamic”,“var”types并返回它们的总和。
因为没有人使用对象提供解决scheme来回答 因此我正在添加我的解决scheme。 在这个你必须把你的通用值的对象。
所以这是工作代码:
public static T Add<T>(T number1, T number2) { object a = number1; object b = number2; return (T)(object)((int)a * (int)b).ToString(); }
试试这个代码。 这是添加的通用代码。
public static dynamic AddAllType(dynamic x, dynamic y) { return x + y; }
正如您从错误消息中看到的那样,运算符“+”不能被应用。 这是因为编译器对Ttypes一无所知。 甚至不知道这是否是一堂课。