【问题标题】:How to declare temporary variables as C# expressions?如何将临时变量声明为 C# 表达式?
【发布时间】:2019-06-08 07:35:22
【问题描述】:

有没有办法在表达式中声明临时变量以重用中间结果?

动机是当您需要在逻辑或转换中多次使用计算结果时,仍然能够使用流畅的调用链和表达式主体方法,例如

public static string Foo(IBar bar)
{
    var result = bar.LongCalculation();

    return result.HasError
        ? throw new Exception()
        : result.ToString();
}

我认为我可以使用 let/select linq 查询关键字,但如果没有 from 子句,这似乎是不可能的,例如

public static string Foo(IBar bar) =>
    let result = bar.LongCalculation()                
    select result.HasError
        ? new Exception()
        : result.ToString();

【问题讨论】:

  • 为什么不调用像LongCalculationSafe这样的表达式主体方法中的方法?然后你可以在那里使用你需要的任何代码。
  • 为什么要使用表达式体法?当正文是单行时,它只是可以使用的语法糖。如果您需要多行,只需使用常规方法语法即可。
  • 我更喜欢函数式流动风格——这是 c# 的方向,并且有兴趣知道它是否有解决方案——因为在逻辑/转换需要重用一个临时的。
  • LINQ 在这里毫无意义。 LINQ 实际上是一个“更好的 foreach”,因为它适用于 collection 并迭代它们。但这不是这里的情况,您正在使用一个单一的result 对象。 LINQ 只处理集合迭代,所以即使你入侵它(例如,通过将你的单个对象放在一个列表中),它也没有任何意义。

标签: c# expression


【解决方案1】:

您可以使用扩展方法:

public static class LongCalculationExtensions
{
    public static ILongCalculationResult ThrowIfHasError(this ILongCalculationResult result)
    {
       if(result.HasError) throw new Exception("Your exception here");

       return result;
    }
}

那么你可以这样使用它:

public static string Foo(IBar bar) => bar.LongCalculation().ThrowIfHasError().ToString();   

【讨论】:

  • 有趣的谢谢。这对于处理常见但不是一般情况的特定情况很有用。顺便说一句,扩展方法可以使用 throw 表达式,因此也可以是表达式。
【解决方案2】:

我之前对Pipe 的回答需要一个 lambda,一个开销更少的更好解决方案是利用内联输出声明:

public static class FunctionalExtensions
{
    public static T Assign<T>(this T o, out T result) =>
        result = o;
}

然后这样称呼它

public static string Foo(IBar bar) =>
    bar.LongCalculation()
       .Assign(out var result)
       .HasError
           ? throw new Exception()
           : result.ToString();

【讨论】:

    【解决方案3】:

    我的首选方法是 Timothy Shields 在这里回答:

    How to "let" in lambda expression?

    创建一个类似于 F# 的管道运算符的扩展方法:

    public static class FunctionalExtensions
    {
        public static TResult Pipe<T, TResult>(this T value, Func<T, TResult> func) =>
            func(value);
    }
    

    然后这样称呼它

    public static string Foo(IBar bar) =>
        bar.LongCalculation()
           .Pipe(result => result.HasError
               ? throw new Exception()
               : result.ToString();
    

    【讨论】:

      猜你喜欢
      • 2013-05-24
      • 2011-12-11
      • 1970-01-01
      • 2021-05-27
      • 2019-05-23
      • 1970-01-01
      相关资源
      最近更新 更多