2013-08-16 23 views
18

coś takiego:Czy są jakieś oficjalne sposoby napisania natychmiastowego wywołania funkcji?

var myObject = new MyClass() 
{ 
    x = " ".Select(y => 
    { 
     //Do stuff.. 
     if (2 + 2 == 5) 
      return "I like cookies"; 
     else if (2 + 2 == 3) 
      return "I like muffins"; 
     //More conditions... 
     else 
      return "I'm a bitter old man"; 
    }) 
}; 

Zdaję sobie sprawę Select nie jest przeznaczony do stosowania w ten sposób. Ale tak, jakie są inne sposoby robienia tego samego?

+5

Jeśli jest zbyt długi, umieść go w funkcji? –

+4

"Jakie są inne sposoby robienia tego samego?" Co próbujesz zrobić? Gdzie jest nieruchomość? – I4V

+4

Nie użyłbym zwrotu w instrukcji select na początek (Plus basic mathematics stwierdza, że ​​jesteś zgorzkniałym staruszkiem). – Sayse

Odpowiedz

11

Jestem zaskoczony nikt nie wspomniał jeszcze, ale można użyć klasy Lazy<T>:

var myObject = new MyClass() 
{ 
    x = new Lazy<string>(() => 
    { 
     //Do stuff.. 
     if (2 + 2 == 5) 
      return "I like cookies"; 
     else if (2 + 2 == 3) 
      return "I like muffins"; 
     //More conditions... 
     else 
      return "I'm a bitter old man"; 
    }).Value // <-- Evaluate the function here 
}; 

Ewentualnie, jeśli chcesz uniknąć konieczności określania typu zwrot wszędzie (jak to zrobić z new Lazy<string> ponieważ konstruktorzy nie obsługują typu wnioskowanie), można zaimplementować prosty sposób ogólny takiego:

public static T Eval<T>(Func<T> func) 
{ 
    return func(); 
} 

a następnie można nazwać tak:

var myObject = new MyClass() 
{ 
    x = Eval(() => 
    { 
     //Do stuff.. 
     if (2 + 2 == 5) 
      return "I like cookies"; 
     else if (2 + 2 == 3) 
      return "I like muffins"; 
     //More conditions... 
     else 
      return "I'm a bitter old man"; 
    }) 
}; 

Aktualizacja: C# 7 wprowadza local functions. Nie są to jednak IFFE, ale mogą rozwiązać wiele powiązanych problemów. Na przykład:

var myObject = new MyClass() 
{ 
    x = GetX() 
}; 

string GetX() { 
    //Do stuff.. 
    if (2 + 2 == 5) 
     return "I like cookies"; 
    else if (2 + 2 == 3) 
     return "I like muffins"; 
    //More conditions... 
    else 
     return "I'm a bitter old man"; 
} 

Kluczem tutaj jest to, że GetX mogą być zadeklarowane w taki sam sposób jak myObject dzielić ten sam zakres jak to.

+0

To jest idealne. Ma sens, nie ma bałaganu w nawiasach i nie ma tam żadnego castingu. – elite5472

13

Dla prawdziwego kodu sprawiają, że funkcja ... do celów rozrywkowych C# odpowiednik JavaScript IIFE jest bardziej bezpośredni niż Select:

var myObject = new MyClass() 
{ 
    x =((Func<int>)(() => {return 2;}))(),... 
+0

+1 za uzyskanie celu tego pytania: D – elite5472

+0

Po prostu użyłem tego do zapełnienia niektórych danych testowych. – QueueHammer

6

Choć z pewnością nie „oficjalnej”, ty mógłby użycie opcjonalnie nazwie parametry konstruktora lub oddzielny sposób fabryka/budowniczy:

public class MyClass 
{ 
    public string x { get; private set; } 

    public MyClass(Func<string> x = null) 
    { 
     if (x != null) 
      this.x = x(); 
    } 
} 

z wykorzystaniem takich jak:

var myClass = new MyClass(
     x:() => 
      { 
       //Do stuff.. 
       if (2 + 2 == 5) 
        return "I like cookies"; 
       else if (2 + 2 == 3) 
        return "I like muffins"; 
       //More conditions... 
       else 
        return "I'm a bitter old man"; 
      } 
    ); 

    Console.WriteLine(myClass.x); //"I'm a bitter old man" 

Tak, to nie jest składnia dokładny pan prosi o, ale dość blisko i pomija weirdness LINQ.

To powiedziawszy, ja nie jak go. Po prostu oferuję to jako pokarm do przemyśleń. :)


EDIT: Pomyślałem, że dodać styl metoda fabryki, ponieważ jest prawdopodobne, że używasz tego na klasy, które nie mogą (lub nie chcą) zmienić jego konstruktora:

public static class MyFactory 
{ 
    public static MyClass CreateMyClass(Func<string> x = null) 
    { 
     var myClass = new MyClass() 

     if (x != null) 
       myClass.x = x(); 

     return myClass; 
    } 
} 

z podobnym użytkowania (tylko wywołanie metody fabryki zamiast):

var myClass = MyFactory.CreateMyClass(
    x:() => 
     { 
      //Do stuff.. 
      if (2 + 2 == 5) 
       return "I like cookies"; 
      else if (2 + 2 == 3) 
       return "I like muffins"; 
      //More conditions... 
      else 
       return "I'm a bitter old man"; 
     } 
); 

EDIT: I hej, a my jesteśmy w nim. Dlaczego nie zejść z głębokiego końca i zrobić to z oddzielnym budowniczym i niejawnymi operatorami!

public class MyClassBuilder 
{ 
    public Func<string> x { get; set; } 

    public static implicit operator MyClass(MyClassBuilder builder) 
    { 
     var myClass = new MyClass(); 

     if (builder.x != null) 
      myClass.x = builder.x(); 

     return myClass; 
    } 
} 

z wykorzystaniem takich jak:

MyClass myClass = new MyClassBuilder 
{ 
    x =() => 
     { 
      //Do stuff.. 
      if (2 + 2 == 5) 
       return "I like cookies"; 
      else if (2 + 2 == 3) 
       return "I like muffins"; 
      //More conditions... 
      else 
       return "I'm a bitter old man"; 
     } 
}; 

Więc teraz składnia jest identyczne, wyjątkiem trzeba jawnie wpisać instancji zamiast korzystania var.

+0

Podczas gdy pierwszy przykład jest interesujący, nie jest to coś, co pytający chciał. Drugi przykład jest najczystszy, jaki widziałem, i ma rację. –

4

Oto co mój współpracownik wymyślił:

var myObject = new { 
    x = new Func<int>(() => {return 2;})() 
}; 

pamiętać, że ta oparta jest odpowiedź Aleksieja.

+0

@DanielGimenez to kompiluje. Po prostu uruchomiłem go na LinqPadzie. Robi także to, co ma robić. – elite5472

+0

Kompiluje i uruchamia na moim komputerze, zarówno na LinqPadzie, jak i studio graficznym. Tak, jest to oparte na odpowiedzi Alexi. – elite5472

+0

OK. Widzę mój błąd, miałeś napis w swoim oryginalnym wpisie, ale zmieniłeś go na int tutaj. –

Powiązane problemy