2009-10-06 20 views
8

Nie sądzę, że możliwe jest użycie operatorów jako parametrów dla metod w C# 3.0, ale czy istnieje sposób naśladowania tego lub jakiegoś syntaktycznego cukru, który sprawia, że ​​wydaje się, że to właśnie się dzieje?Operatory jako parametry metody w C#

pytam bo ostatnio wdrożone the thrush combinator in C# ale podczas tłumaczenia Raganwald's Ruby example

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

który brzmi „Take numery od 1 do 100, zachować nieparzystych, wziąć sumę tych, a następnie odpowiedzieć na kwadrat o tej liczbie. "

Upadłem na rzeczy z Symbol#to_proc. To jest &: w powyższym select(&:odd?) i inject(&:+).

Odpowiedz

8

Cóż, w prosty sposób można po prostu użyć 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 

to nie jest bardzo ekscytujące, choć. Byłoby miło, gdyby wszyscy delegaci zostali do nas stworzeni. Oczywiście można zrobić to z klasą statyczną:

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

Rzeczywiście, Marc Gravell ma done something very similar w MiscUtil, jeśli chcesz wyglądać. Następnie można nazwać:

DoSomething(Operator<int>.Plus); 

Nie jest to ładna, ale to, że najbliższa jest obsługiwana w tym momencie, jak sądzę.

Obawiam się, że tak naprawdę nie rozumieją rzeczy Ruby, więc nie mogę się wypowiedzieć na ten temat ...

+0

Doskonała odpowiedź, klasa Operator wydaje się być dość dużo dokładnie to, czego szukałem. Wypróbuję to później. –

2

Poniżej znajduje bezpośrednie, dosłowne (w miarę możliwości) C# tłumaczenia:

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

Konkretnie:

  • bloki: {||} - zostań lambdas: =>
  • select staje Where
  • inject staje Aggregate
  • into staje się bezpośrednia rozmowa na przykład lambda
+0

Bardzo ładnie, oprócz tego, że pomija punkt kombinatora Thrush, który w tym przypadku przesuwa x * x do końca w celu uzyskania czytelności. I tak warto dać +1. –

+0

Nie zdawałem sobie sprawy, że tak jest - po prostu przyjrzałem się tłumaczeniu Scala, które robi to samo, co zrobiłem. Powiedziawszy to, '.Into()' może być napisane trywialnie jako metoda rozszerzenia, jeśli jest to potrzebne. –

+0

realizacja Ghosh Scala jest bardzo ładny: (1 do 100) .filter (_% 2 = 0!) .foldLeft (0) (_ + _) .into ((x: Int) = > x * x) –