2009-08-27 17 views
18

Czy można wyrzucać argumenty param w C#? Mam:Przesyłanie parametrów C# out?

Dictionary<string,object> dict; // but I know all values are strings 
string key, value; 

Ogólnie rzecz biorąc (i jeśli nie mam pisać statyczny) chcę zrobić:

dict.TryGetValue(key, out value); 

ale to oczywiście nie będzie kompilować, ponieważ „nie można przekonwertować z„out ciąg "do" obiektu "".

Obejście używam to:

object valueAsObject; 
dict.TryGetValue(key, out valueAsObject); 
value = (string) valueAsObject; 

ale to wydaje się raczej niewygodne.

Czy jest jakaś funkcja językowa, która pozwala mi rzucić na zewnątrz w wywołaniu metody, więc robi to dla mnie ten krosk? Nie mogę znaleźć żadnej składni, która pomoże, i nie mogę znaleźć niczego w Google.

Odpowiedz

2

Jeśli wiesz, że wszystkie wartości są ciągami, użyj zamiast tego Dictionary<string, string>. Typ parametru out jest ustawiany według typu drugiego parametru typu ogólnego. Ponieważ twój jest obecnie obiektem, zwróci obiekt podczas pobierania ze słownika. Jeśli zmienisz go na ciąg, zwróci ciągi.

+4

The Słownik jest dostarczany przez interfejs, którego używam. Wiem, że wszystkie wartości są ciągami dla mojego korzystania z tego, ponieważ to właśnie tutaj wypełniam. – Ken

0

Nie, nie możesz. Kod wewnątrz metody bezpośrednio modyfikuje przekazaną do niego zmienną, nie przekazuje się jej kopii zawartości zmiennej.

2

Nie, nie da się tego obejść. Parametr out musi mieć zmienną, która dokładnie pasuje.

Używanie odwołania do ciągu nie jest bezpieczne, ponieważ słownik może zawierać inne rzeczy niż łańcuchy. Jednak gdybyś miał słownik ciągów znaków i próbował użyć zmiennej obiektu w wywołaniu TryGetValue, to nie zadziała, nawet jeśli byłoby to bezpieczne. Typ zmiennej musi dokładnie pasować.

18

Nie wiem, czy jest to świetny pomysł, ale można dodać ogólną metodę rozszerzenia:

static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      value = (TActual)tmp; 
      return true; 
     } 
     value = default(TActual); 
     return false; 
    } 
    static void Main() 
    { 
     Dictionary<string,object> dict 
      = new Dictionary<string,object>(); 
     dict.Add("abc","def"); 
     string key = "abc", value; 
     dict.TryGetTypedValue(key, out value); 
    } 
+0

To interesujący kawałek cukru syntaktycznego. –

+0

+1 nigdy nie robiłem tego w słowniku, ale mam bardzo podobne metody pomocnicze. –

+1

Jedyną rzeczą, którą mógłbym ewentualnie zmienić, byłaby obsługa przypadku, w którym znaleziono wartość, ale jest ona niewłaściwego typu. Zamiast rzucać, mogę chcieć, aby po prostu zwrócił fałsz. Z drugiej strony, może nie. Musiałbym to przemyśleć, ale warto o tym wspomnieć. –

2

użyłem metody rozszerzenie Marca ale dodaje trochę do niego.

Mój problem z oryginałem polegał na tym, że w niektórych przypadkach mój słownik zawierał int64, podczas gdy ja oczekiwałbym na 32. W innych przypadkach słownik zawierałby ciąg (na przykład "42"), podczas gdy chciałbym uzyskać to jako int.

Nie ma sposobu, aby obsłużyć konwersję w metodzie Marca więc dodałem zdolność przechodzenia na delegata do sposobu konwersji:

internal static bool TryGetTypedValue<TKey, TValue, TActual>(
     this IDictionary<TKey, TValue> data, 
     TKey key, 
     out TActual value, Func<TValue, TActual> converter = null) where TActual : TValue 
    { 
     TValue tmp; 
     if (data.TryGetValue(key, out tmp)) 
     { 
      if (converter != null) 
      { 
       value = converter(tmp); 
       return true; 
      } 
      if (tmp is TActual) 
      { 
       value = (TActual) tmp; 
       return true; 
      } 
      value = default(TActual); 
      return false; 
     } 
     value = default(TActual); 
     return false; 
    } 

który można nazwać tak:

int limit; 
myParameters.TryGetTypedValue("limitValue", out limit, Convert.ToInt32) 
Powiązane problemy