【问题标题】:Operators as method parameters in C#运算符作为 C# 中的方法参数
【发布时间】:2009-10-06 21:57:19
【问题描述】:

我认为在 C# 3.0 中不可能将运算符用作方法的参数,但有没有办法模拟那个或一些语法糖,让它看起来像是发生了什么?

我问是因为我最近实现了the thrush combinator in C#,但是在翻译Raganwald's Ruby example

(1..100).select(&:odd?).inject(&:+).into { |x| x * x }

上面写着“取 1 到 100 的数字,保留奇数,取它们的总和,然后回答该数字的平方。”

我对@9​​87654323@ 的东西不满意。这就是上面select(&:odd?)inject(&:+) 中的&:。

【问题讨论】:

    标签: c# ruby lambda extension-methods


    【解决方案1】:

    嗯,简单来说,你可以只使用 lambda:

    public void DoSomething(Func<int, int, int> op)
    {
        Console.WriteLine(op(5, 2));
    }
    
    DoSomething((x, y) => x + y);
    DoSomething((x, y) => x * y);
    // etc
    

    不过,这并不是很令人兴奋。为我们预先构建所有这些代表会很好。当然你可以用一个静态类来做到这一点:

    public static class Operator<T>
    {
         public static readonly Func<T, T, T> Plus;
         public static readonly Func<T, T, T> Minus;
         // etc
    
         static Operator()
         {
             // Build the delegates using expression trees, probably
         }
    }
    

    确实,如果你想看的话,Marc Gravell 在MiscUtil 中有done something very similar。然后你可以打电话:

    DoSomething(Operator<int>.Plus);
    

    它不是很漂亮,但我相信它是目前支持的最接近的。

    恐怕我真的不懂 Ruby 的东西,所以我不能对此发表评论......

    【讨论】:

    • 很好的答案,Operator 类似乎正是我想要的。不过稍后会尝试一下。
    【解决方案2】:

    以下是直接、字面(尽可能)的C#翻译:

    (Func<int>)(x => x * x)(
        Enumerable.Range(1, 100)
            .Where(x => x % 2 == 1)
            .Aggregate((x, y) => x + y))
    

    具体来说:

    • 块:{||} - 变成 lambdas:=&gt;
    • select 变为 Where
    • inject 变为 Aggregate
    • into 成为对 lambda 实例的直接调用

    【讨论】:

    • 非常好,只是它错过了画眉组合器的要点,在这种情况下,为了便于阅读,它会将 x*x 移动到末尾。无论如何都值得 +1。
    • 没有意识到是这样的——我只是看了 Scala 翻译,它和我做的一样。也就是说,如果需要,.Into() 可以简单地编写为扩展方法。
    • Ghosh 的 Scala 实现非常好: (1 to 100) .filter(_ % 2 != 0) .foldLeft(0)(_ + _) .into((x: Int) => x * x)
    • 是的,占位符简化了一些事情。实际上,想想看,C# 有运算符重载,所以我认为可以定义 _ 并为其重载运算符,从而产生 lambdas ......它不会让你写 @ 987654331@ 就像 Scala 一样,但它会让你写 _ + 1 甚至 _ + _。我需要考虑一下。
    猜你喜欢
    • 2017-11-18
    • 2018-09-22
    • 2020-09-01
    • 1970-01-01
    • 2019-07-03
    • 2018-10-28
    • 1970-01-01
    • 2014-09-23
    • 2018-03-26
    相关资源
    最近更新 更多