2009-10-06 15 views
8

Ich glaube nicht, dass es möglich ist, Operatoren als Parameter zu Methoden in C# 3.0 zu verwenden, aber gibt es eine Möglichkeit, diesen oder einen syntaktischen Zucker zu emulieren, der es so aussehen lässt?Operatoren als Methodenparameter in C#

Ich frage, weil ich vor kurzem the thrush combinator in C# umgesetzt, aber beim Übersetzen Raganwald's Ruby example

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

Welche „die Zahlen von 1 bis 100 Nehmen Sie liest, die ungeraden zu halten, nehmen Sie die Summe derer, und beantworten Sie dann die Quadrat dieser Zahl. "

Ich fiel auf die Symbol#to_proc Sachen. Das ist die &: in der select(&:odd?) und der inject(&:+) oben.

Antwort

8

Nun, in einfachen Worten kann man nur einen Lambda verwenden:

public void DoSomething(Func<int, int, int> op) 
{ 
    Console.WriteLine(op(5, 2)); 
} 

DoSomething((x, y) => x + y); 
DoSomething((x, y) => x * y); 
// etc 

, dass, obwohl nicht sehr aufregend ist. Es wäre schön, wenn all diese Delegierten für uns vorgefertigt wären. Natürlich könnte man dies mit einer statischen Klasse tun:

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 
    } 
} 

Tat Marc GRA hat done something very similar in MiscUtil, wenn Sie aussehen wollen. Sie könnten dann rufen:

DoSomething(Operator<int>.Plus); 

Es ist nicht gerade schön, aber es ist in der Nähe, die im Moment unterstützt wird, glaube ich.

Ich fürchte, ich verstehe wirklich nicht, das Zeug Rubin, so kann ich dazu nichts sagen ...

+0

Ausgezeichnete Antwort, die Operator-Klasse so ziemlich genau das, was ich suchte. Werde es später ausprobieren. –

2

Hier finden Sie direkte, wörtliche (so viel wie möglich) C# Übersetzung:

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

Im Einzelnen:

  • Blöcke: {||} - werden lambdas: =>
  • select wird Where
  • injectAggregate
  • into wird ein direkter Anruf auf einer Lambda-Instanz scheint wird
+0

Sehr schön, außer dass es den Punkt des Thrush-Kombinators verfehlt, der in diesem Fall das x * x an das Ende zur besseren Lesbarkeit verschieben soll. Jedenfalls ein +1 wert. –

+0

Ist mir nicht klar, dass das der Fall ist - ich habe mir nur die Scala-Übersetzung angesehen, die dasselbe tut wie ich. Das heißt, '.Into()' könnte trivialerweise als eine Erweiterungsmethode geschrieben werden, falls gewünscht. –

+0

Ghosh Scala Umsetzung ist sehr schön: (1 bis 100) .filter (_% 2 = 0!) .foldLeft (0) (_ + _) .into ((x: Int) = > x * x) –