C#添加两个通用值

And*_*ans 34 generics c#-4.0

有人可以解释为什么这不起作用?无论数字类型如何,我都试图能够添加两个值.

public static T Add<T> (T number1, T number2)
{
    return number1 + number2;
}
Run Code Online (Sandbox Code Playgroud)

当我编译它时,我收到以下错误:

Operator '+' cannot be applied to operands of type 'T' and 'T'
Run Code Online (Sandbox Code Playgroud)

Dar*_*rov 64

没有允许您强制运算符重载的通用约束.您可以查看以下库.或者,如果您使用的是.NET 4.0,则可以使用以下dynamic关键字:

public static T Add<T>(T number1, T number2)
{
    dynamic a = number1;
    dynamic b = number2;
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

显然,这不适用于任何编译时安全性,这是泛型的意思.应用编译时安全性的唯一方法是强制执行通用约束.对于您的场景,没有可用的约束.这只是欺骗编译器的技巧.如果Add方法的调用者没有传递与+运算符一起使用的类型,则代码将在运行时抛出异常.

  • @Aamir “where”约束一直存在。关键是没有办法在 where 子句中指定“可以将 T 添加到其他 T 的位置”:) (2认同)

Adi*_*ter 28

这里给出的解决方案运行良好,但我想我会添加另一个使用表达式的解决方案

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);
}
Run Code Online (Sandbox Code Playgroud)

这样你就可以创建一个Func<T, T, T>执行添加的方法.完整的解释可以在本文中找到.


Ric*_*lly 11

编译器不知道类型T,因此找不到任何地方定义的重载+运算符...

您当前可以做的最好的方法是声明您的方法(因为所有数字类型都可以转换为double):

public static double Add (double number1, double number2)
{
  return number1 + number2;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您确定将定义合适的+运算符:

public static T Add<T>(T number1, T number2)
{
  dynamic dynamic1 = number1;
  dynamic dynamic2 = number2;
  return dynamic1 + dynamic2;
}
Run Code Online (Sandbox Code Playgroud)

更新

或两者的组合:

public static T Add<T>(T in1, T in2)
{
    var d1 = Convert.ToDouble(in1);
    var d2 = Convert.ToDouble(in2);
    return (T)(dynamic)(d1 + d2);
}
Run Code Online (Sandbox Code Playgroud)

  • @kol好点,从我的回答中隐含删除. (3认同)
  • 小数不能隐式转换为double. (2认同)

Bra*_*oat 6

当我想要一个可以在任意数字列表上工作的泛型方法时,我就遇到了这个问题,例如:

public T Calculate<T>(IEnumerable<T> numbers);
Run Code Online (Sandbox Code Playgroud)

我发现的解决方案是使用lambda表达式:

public T Calculate<T>(Func<T, T, T> add, IEnumerable<T> numbers);
Run Code Online (Sandbox Code Playgroud)

然后你打电话给谁

var sum = this.Calculate((a, b) => a + b, someListOfNumbers);
Run Code Online (Sandbox Code Playgroud)

显然在某些情况下,您可能只是在代码中使用+而不是lambda表达式,但如果您需要以通用方式执行数学运算,这是我能想到的最简单的事情,即编译安全.


Ira*_*Ira 5

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);
}
Run Code Online (Sandbox Code Playgroud)