【问题标题】:Variance in Func<> argumentsFunc<> 参数的差异
【发布时间】:2013-11-23 23:36:40
【问题描述】:

我一直在尝试做类似的事情

Func<string, bool> f
Func<object, bool> F = f;

并且编译器会引发以下错误:

无法将类型 'System.Func&lt;string,bool&gt;' 隐式转换为 'System.Func&lt;object,bool&gt;'

但是,我们显然可以做到object x = "123"

【问题讨论】:

    标签: c# c#-4.0 generics lambda variance


    【解决方案1】:

    想象一下,如果你这样做了:

    Func<string, bool> fStr = str => str.Length > 10;
    Func<object, bool> fObj = fStr;
    

    嗯,根据fObj的签名,你应该可以用任何这样的参数调用它:

    fObj(7);
    

    这显然对fStr无效。

    【讨论】:

    • +1。经典之一。使用接口会起作用,但我无权访问代码。我将不得不重新设计我的逻辑。
    • 您不必使用接口。你只是把你的任务倒过来了。 Func&lt;object, bool&gt; 可以分配给Func&lt;string, bool&gt;,但由于第一个参数是逆变的(在关键字中),因此不能相反。然而,第二个参数是协变的(out 关键字),这意味着像Func&lt;bool, string&gt; 这样的东西可以分配给Func&lt;bool, object&gt;
    【解决方案2】:

    委托类型Func&lt;in T, out TResult&gt; 在其第一个类型参数T 中显然是逆变。可以接受任何对象的“func”也可以接受字符串,所以Func&lt;object, X&gt;“是一个”Func&lt;string, X&gt;,所以这是in类型T中的逆变。

    你正试图走另一条路。仅当您碰巧知道运行时类型实际上是Func&lt;object, bool&gt; 时才有效,并且您将需要显式转换语法来告知编译器您的知识。如果运行时类型不正确,显式转换将失败。

    有效示例:

    Func<object, bool> f1 = XXX;
    Func<string, bool> f2 = f1;                      // OK, implicit
    Func<object, bool> f3 = (Func<object, bool>)f2;  // OK, explicit
    

    【讨论】:

      【解决方案3】:

      来自MSDN

      隐式转换: 不需要特殊语法,因为转换是类型安全的,不会丢失任何数据。示例包括从较小的整数类型到较大的整数类型的转换,以及从派生类到基类的转换。

      显式转换(强制转换):显式转换需要强制转换运算符。当转换中可能会丢失信息,或者由于其他原因转换可能不成功时,需要进行强制转换。典型示例包括将数值转换为精度较低或范围较小的类型,以及将基类实例转换为派生类。

      你不能这样做,因为你会丢失信息。 如果你想换一种方式,你可以这样做

       Func<object, bool> f = ....;
       Func<string, bool> F = f;
      

      因为您不会丢失信息。

      一个简单的例子是:

      // This is ok. you can fit int in double
      int some_int = 42;
      double some_double = some_int;
      
      // This is not ok. you might lose information
      double some_double_2 = 42;
      int some_int_2 = some_double_2;
      
      
      // But you could do this, where the casts says: "Yep, I'm aware I might lose some
      // information, but I'm an UBER programmer and want to do it anyways"
      int some_int_3 = (int)some_double_2;
      

      您可以投射或编写自己的默认转换。看看上面的 MSDN 链接 :)

      【讨论】:

      • 这个答案并没有真正解决Func&lt;in T, out TResult&gt;的方差问题。这与丢失信息无关,与扩大和缩小数字转换无关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-27
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      相关资源
      最近更新 更多