2011-11-14 57 views
20

有人可以解釋爲什麼這不起作用嗎?我試圖能夠添加兩個值,無論數字類型。C#添加兩個通用值

public static T Add<T> (T number1, T number2) 
{ 
    return number1 + number2; 
} 

當我編譯,我得到以下錯誤:

Operator '+' cannot be applied to operands of type 'T' and 'T' 
+1

C#編譯器做這個,所以你不寫bug的代碼。如果編譯器不知道T,它不知道如何添加T值。它也不知道T的結果類型,在這種情況下是加法。 – JonH

+0

參數是否被強制爲「數字類型」? –

回答

40

有沒有通用的約束,允許您強制執行操作符重載。您可以查看following library。另外,如果您使用的是.NET 4.0中,您可以使用關鍵字dynamic

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

顯然,這並不適用於任何編譯時安全這正是泛型都是爲了。應用編譯時安全性的唯一方法是強制執行通用約束。對於您的場景,沒有可用的限制。這只是欺騙編譯器的一個技巧。如果Add方法的調用方不傳遞與+運算符一起工作的類型,則代碼將在運行時拋出異常。

+1

+1以解釋和傳遞不良數據的結果。 – JonH

+0

我想現在有哪裏約束..詳細信息[這裏](https://msdn.microsoft.com/en-us/library/bb384067.aspx) – Aamir

+0

@Aamir「where」約束一直存在。重點是,沒有辦法指定「where T可以添加到其他Ts」中的where子句:) – Frans

-2

正如你從錯誤信息運營商「+」看不能適用。 這是因爲編譯器對T類型一無所知。 甚至不知道這是否是一堂課。

+2

不是一個好的答案。 – JonH

+0

@JonH嗯..可能你是對的。我不知道如何用幾句話來解釋C#泛型相對於C++模板的比較非常有限 – VMykyt

+1

這與限制無關。如果做得好,幾乎任何事情都有可能。您的原始答案是「從錯誤消息運算符+無法應用」中看到的。這不是一個好的答案,我沒有倒下,但事實並非如此。 – JonH

8

T型不是由編譯器知道,所以它不能找到任何地方定義的重載+操作...

目前可以做的最好的就是聲明你的方法,這樣的(因爲所有的數字類型轉換爲雙):

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); 
} 
+1

小數不能轉換爲雙隱式。 – kol

+2

@kol好的一點,從我的答案隱含刪除。 –

3

這是我剛當我想要一個通用的方法,可以在數任意名單工作,例如一個問題:

public T Calculate<T>(IEnumerable<T> numbers); 

我找到的解決方案是使用lambda表達式:

public T Calculate<T>(Func<T, T, T> add, IEnumerable<T> numbers); 

哪個你最好的通過

var sum = this.Calculate((a, b) => a + b, someListOfNumbers); 

很顯然,在某些情況下,你可能也只是有+的代碼,而不是lambda表達式內,但如果你需要了一般方法這個執行數學運算n個通話是最容易的事情我可以拿出那個編譯安全。

15

這裏給出的解決方案的工作很好,但我想我會再添一個,它使用表達式

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); 
} 

這樣,你要創建一個Func<T, T, T>執行加法。 詳細解釋請參見this article

1
 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); 

     } 
3
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); 
} 
1

這防止開發者編寫缺陷代碼。有幾個問題可以更好地解釋這個問題:

1>編譯器是否知道類型[No,因爲它是泛型類型]。 2>它可以接受的對象作爲參數[是的,它可以,因爲它不會知道如何處理它們 - >越野車代碼]

因爲,你想防止你的代碼是越野車, C#不允許你有'+'''和其他操作符。

解決方案: 如果需要,您可以使用「dynamic」,「var」類型並返回它們的總和。

1

因爲沒有人通過使用對象提供解決方案來回答。因此我正在添加我的解決方案。在這你必須將你的通用值轉換爲對象。

因此,這是工作代碼:

1

試試這個代碼。這是添加的通用代碼。

public static dynamic AddAllType(dynamic x, dynamic y) 
{ 
    return x + y; 
}