【问题标题】:C# Func and Conditional OperatorC# Func 和条件运算符
【发布时间】:2010-10-26 19:25:14
【问题描述】:

Duplicate

我可以这样做:

Func<CategorySummary, decimal> orderByFunc;
if (orderBy == OrderProductsByProperty.Speed)
     orderByFunc = x => x.Speed;
else
    orderByFunc = x => x.Price;

为什么我不能这样做:

Func<CategorySummary, decimal> orderByFunc = (orderBy == OrderProductsByProperty.Speed) ? x => x.Speed : x => x.Price;

【问题讨论】:

  • 语言规范要求条件表达式的类型是已知的。条件表达式的类型取决于结果和替代的类型,但在您的情况下,它们都没有类型——lambdas 是无类型的。

标签: c#


【解决方案1】:

条件运算符的“类型推断”不够好,我收到类似的消息

条件表达式的类型不能 确定,因为没有 'lambda 之间的隐式转换 表达式'和'lambda表达式'

你总是可以在右手边显式地显示,一个拉

var o = true ? new Func<int,int>(x => 0) : new Func<int,int>(x => 1);

无论如何,这只是关于 lambda 类型、类型推断和条件运算符如何交互的小麻烦。

【讨论】:

    【解决方案2】:

    只需将 lambda 转换为 Func&lt;CategorySummary, decimal&gt; 就可以了

    【讨论】:

      【解决方案3】:

      目前建议的替代方案 - 将条件移动到 lambda 表达式中:

      Func<CategorySummary, decimal> orderByFunc = 
          x => (orderBy == OrderProductsByProperty.Speed) ? x.Speed : x.Price;
      

      它可能并不适用于所有情况(这确实意味着每次调用都会执行检查),但有时它可能很有用。

      编辑:正如 Eric 指出的那样,两者并不等同。下面是一个快速示例,说明它们的不同之处(使用显式转换来使条件在操作数为 lambda 的情况下工作):

      using System;
      
      class Test
      {   
          static void Main()
          {
              bool likesCheese = false;
      
              Action outerConditional = likesCheese 
                  ? (Action) (() => Console.WriteLine("Outer: I like cheese"))
                  : (Action) (() => Console.WriteLine("Outer: I hate cheese"));
      
              Action innerConditional = () => 
                  Console.WriteLine (likesCheese ? "Inner: I like cheese" 
                                                 : "Inner: I hate cheese");
      
      
              Console.WriteLine("Before change...");
              outerConditional();
              innerConditional();
      
              likesCheese = true;
              Console.WriteLine("After change...");
              outerConditional();
              innerConditional();
          }
      }
      

      结果:

      Before change...
      Outer: I hate cheese
      Inner: I hate cheese
      After change...
      Outer: I hate cheese
      Inner: I like cheese
      

      如您所见,likesCheese 的值的更改仅影响在 lambda 表达式内部具有条件运算符的版本。有时这是可取的,有时不是……但您绝对需要意识到这一点。

      【讨论】:

      • 请注意,这样做可能会改变程序的语义。原始程序在创建委托时使用“orderBy”的值进行选择。您的版本在执行委托时使用“orderBy”的值,但可能会有所不同。
      【解决方案4】:

      只需将一个结果操作数转换为目标类型就足够了:

      Action showResult = true 
          ? (Action)(() => Console.Write("Hello!"))
          : () => Console.Write("");
      

      这有点出乎意料,但这就是编译器的工作方式。当我想到它时,它现在是有道理的。

      【讨论】:

        猜你喜欢
        • 2011-03-11
        • 2011-03-21
        • 1970-01-01
        • 1970-01-01
        • 2011-04-24
        • 2020-08-19
        • 1970-01-01
        • 2020-10-06
        • 2010-11-08
        相关资源
        最近更新 更多