2012-08-26 11 views
7

W języku C# można w locie utworzyć nową funkcję, aby zdefiniować zmienną?C# Variable = new function() {};

wiem, że

string getResult() { 
    if (a) 
     return "a"; 
    return "b"; 
} 
String result = getResult(); 

jest możliwe, ale ja szukam czegoś podobnego

String result = new string getResult() { 
    if (a) 
     return "a"; 
    return "b"; 
} 

to jest możliwe? Jeśli tak, czy ktoś by to wykazał?

EDIT Jest możliwe

Edit: Final - Rozwiązanie

To jest końcowy wynik, co ja barbarzyńsko hacked razem

Func<string> getResult =() => 
{ 
    switch (SC.Status) 
    { 
     case ServiceControllerStatus.Running: 
      return "Running"; 
     case ServiceControllerStatus.Stopped: 
      return "Stopped"; 
     case ServiceControllerStatus.Paused: 
      return "Paused"; 
     case ServiceControllerStatus.StopPending: 
      return "Stopping"; 
     case ServiceControllerStatus.StartPending: 
      return "Starting"; 
     default: 
      return "Status Changing"; 
    } 
}; 

TrayIcon.Text = "Service Status - " + getResult(); 

Odpowiedz

6

Jednym ze sposobów, aby określić taką funkcję:

Func<bool, string> getResult = (a) => { 
    if (a) 
     return "a"; 
    return "b"; 
} 

Następnie można wywołać: string foo = getResult(true);. Jako delegat może być przechowywany/przekazywany i wywoływany w razie potrzeby.

Przykład:

string Foo(Func<bool, string> resultGetter){ 
    return resultGetter(false); 
} 

Można również close wokół zmiennych w zakresie:

bool a = true; 

Func<string> getResult =() => { 
    if (a) 
     return "a"; 
    return "b"; 
} 

string result = getResult(); 
+0

(Jeśli rozumiem intencję pytającego ...) Polecam przeciw temu, ponieważ nie jest to coś, do czego zwykle używane są funkcje "Func" i może być mylące dla przyszłych czytelników twojego kodu (do ciebie włącznie), które są bardziej znane z normalnymi wzorami użycia 'Func'. Chyba że jest to naprawdę instancja, w której "Func" lub "Akcja" ma więcej sensu, albo wstawiaj kod, albo uczyń go osobną metodą. –

+0

Musiałbym się nie zgodzić. Chociaż nie wiem, jakie są potrzeby PO, a jest to wymyślny przykład, umiejętność definiowania i wielokrotnego/warunkowego/ostatecznego wykonania delegata jest zarówno silna, jak i powszechna. Ale to tylko ja. –

+0

To tak naprawdę nie działa dla mnie tak, jak Tim S. stwierdził. Wolałbym zdefiniować go w osobnej metodzie, gdybym używał tej trasy. Moim jedynym prawdziwym celem w tym celu było zdefiniowanie tego leniwego stylu w jednym wierszu, jak Actionscript, lub co uważam za możliwe również w Javo. Kiedy zdałem sobie sprawę, że może to być trudniejsze, niż początkowo zamierzałem, byłem ciekawy, jak można to zaimplementować, jeśli faktycznie można go wdrożyć. –

2

Chcesz użyć instrukcja inline.

string result = a ? "a" : "b"; 
+0

czuję się jak to będzie działać, chyba że ja rzeczywiście próbuje wdrożyć przełącznika. Uprośniłem go do instrukcji if w moim kodzie, aby spróbować być zrozumianym. Czy istnieje prawdopodobnie wbudowana instrukcja przełączania? –

+1

można to zrobić za pomocą 'Słownika'. –

+0

Słownik 'Dictionary' ma znacznie więcej narzutów niż prosta instrukcja switch (relatywnie rzecz biorąc). Generalnie powinieneś unikać używania słowników dla logiki znanej podczas kompilacji. – MgSam

0

Nie wiesz, co zakres zmiennej a jest w przykładzie, ale przy założeniu, że jest on dostępny w ciągu Zakres (jak w twoim przykładzie):

Func<string> getResult =() => 
{ 
    return a ? "a" : "b"; 
} 
+1

'Działanie ' s nie zwracaj niczego; miałeś na myśli 'Func '? W każdym razie, myślę, że 'var' prawdopodobnie zadziała ... – Ryan

+0

@minitech yes updated thanks. –

+0

@minitech, 'var' nie działa z lambdas. Nie ma wystarczającego kontekstu, aby kompilator wiedział, co z niego zrobić. (błąd kompilatora to "Nie można przypisać wyrażenia lambda do niejawnie wpisanej zmiennej lokalnej"). –

0

Opierając się na opublikowanym przez ciebie rozwiązaniu, oto lepszy sposób na zrobienie tego.

Zmień ServiceControllerStatus enum dodać [Opis] atrybuty:

public enum ServiceControllerStatus 
{ 
    [Description("Running")] 
    Running, 
    // ... others 
} 

Dodaj następującą metodę rozszerzenia w nowej klasie statycznej:

public static string ToDescription(this Enum value) 
{ 
    var attributes = (DescriptionAttribute[])value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false); 
    return attributes.Length > 0 ? attributes[0].Description : value.ToString(); 
} 

Teraz można po prostu napisać:

TrayIcon.Text = "Service Status - " SC.Status.ToDescription(); 
1

Jeśli naprawdę chcesz, możesz wstawiać metodę rozszerzenia dla typu String:

static class StringExtensions { 
    public static string ExecuteFunc(
      this string str, 
      Func<string, string> func 
     ) { 
     return func(str); 
    } 
} 

I wtedy, gdy chcesz go używać, to zrobić tak:

string str = "foo"; 

string result = str.ExecuteFunc(s => { 
     switch(s){ 
      case "a": 
       return "A"; 
      default: 
       return "B"; 
     } 
    } 
); 
+0

+1 za używanie rozszerzenia. Chociaż tak naprawdę nie przekazuje funkcji. Nie można go przypisać tylko raz, ale trzeba go przypisać po każdym wywołaniu. – liang