2013-02-24 5 views
2

Я совершенно сбиты с толку этой ошибки:не удается преобразовать из Func <T,T,T> в Func <T,T,T>

Cannot implicitly convert type 'System.Func<T,T,T> [c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll]' to 'System.Func<T,T,T> [c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll]' path\to\my\project\Operators.cs

типы идентичны, почему он даже пытается сделать бросок? Вот код:

public static class Operators<T> 
{ 
    private static Func<T,T,T> _add = null; 

    public static T Add<T>(T a, T b) 
    { 
     if (_add == null) { 
      var param1Expr = Expression.Parameter(typeof (T)); 
      var param2Expr = Expression.Parameter(typeof (T)); 
      var addExpr = Expression.Add(param1Expr, param2Expr); 
      var expr = Expression.Lambda<Func<T, T, T>>(addExpr, param1Expr, param2Expr); 
      _add = expr.Compile(); // <--- error occurs here 
     } 
     return _add.Invoke(a, b); 
    } 
} 
+1

Вы должны были получить предупреждение об этом от компилятора. Не так ли? –

+0

@EricLippert: Появилось предупреждение, но я мгновенно их отключил, поскольку я реорганизовал кучу вещей, и я получал слишком много предупреждений о неиспользуемых переменных. – mpen

ответ

13

Проблема заключается в том, что ваш метод является универсальным, вводя новый параметр типа T. Таким образом, T вне метода не совпадает с T внутри метода.

Просто измените способ не быть универсальным:

public static T Add(T a, T b) 

... и это должно быть хорошо.

Чтобы быть более ясным, что ваш код в настоящее время эквивалентно к этому:

public static class Operators<TC> 
{ 
    private static Func<TC, TC, TC> _add = null; 

    public static TM Add<TM>(TM a, TM b) 
    { 
     if (_add == null) { 
      var param1Expr = Expression.Parameter(typeof(TM)); 
      var param2Expr = Expression.Parameter(typeof(TM)); 
      var addExpr = Expression.Add(param1Expr, param2Expr); 
      var expr = Expression.Lambda<Func<TM, TM, TM>> 
          (addExpr, param1Expr, param2Expr); 
      _add = expr.Compile(); 
     } 
     return _add.Invoke(a, b); 
    } 
} 

Обратите внимание, как я переименовал T введенную класса к TC и T ввести методом - TM. Сообщение об ошибке выглядит более разумным:

Test.cs(19,20): error CS0029: Cannot implicitly convert type 
     'System.Func<TM,TM,TM>' to 'System.Func<TC,TC,TC>' 
2

T для Operators<T> класса и параметр T типа для Add различных типов, так что нет никакой гарантии, что типы совместимы.

Например, вы могли бы сделать:

Operators<string>.Add<int>(1, 2); 

Компилятор выдает предупреждение на этот счет:

Type parameter 'T' has the same name as the type parameter from outer type 'Operators'

+0

Хорошо видно на переднем плане. Всегда стоит сначала проверить предупреждения :) –

+0

Hah. У меня были предупреждения отключены, потому что это был спам о переменных, которые я объявил, но еще не использовал :-) Служит мне правильно. – mpen

Смежные вопросы