【问题标题】:Cannot convert from Func<T,T,T> to Func<T,T,T>无法从 Func<T,T,T> 转换为 Func<T,T,T>
【发布时间】:2013-02-24 19:50:55
【问题描述】:

我对这个错误感到很困惑:

Cannot implicitly convert type 'System.Func&lt;T,T,T&gt; [c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\mscorlib.dll]' to 'System.Func&lt;T,T,T&gt; [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);
    }
}

【问题讨论】:

  • 你应该从编译器那里得到一个警告。你没有吗?
  • @EricLippert:有一个警告,但我暂时关闭了它们,因为我正在重构一堆东西,并且收到太多关于未使用变量的警告。

标签: c# generics casting delegates


【解决方案1】:

问题是你的方法是通用的,引入了一个新的类型参数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】:

    Operators&lt;T&gt; 类的TAddT 类型参数是不同的类型,因此不能保证这些类型是兼容的。

    例如你可以这样做:

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

    编译器会为此发出警告:

    类型参数 'T' 与外部的类型参数同名 输入“运营商”

    【讨论】:

    • 在警告前面有很好的发现。首先检查警告总是值得的 :)
    • 哈。我关闭了警告,因为它正在向我声明但尚未使用的变量发送垃圾邮件:-) 为我服务。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2011-10-31
    • 2010-10-20
    相关资源
    最近更新 更多