Przekazywanie właściwości jako parametru „out” w języku C #

81

Załóżmy, że mam:

public class Bob
{
    public int Value { get; set; }
}

Chcę przekazać element członkowski Value jako parametr wyjściowy, taki jak

Int32.TryParse("123", out bob.Value);

ale pojawia się błąd kompilacji, argument „out” nie jest klasyfikowany jako zmienna. " Czy jest jakiś sposób, aby to osiągnąć, czy też będę musiał wyodrębnić zmienną à la:

int value;
Int32.TryParse("123", out value);
bob.Value = value;
thorncp
źródło

Odpowiedzi:

83

Musiałbyś jawnie użyć pola i „zwykłej” właściwości zamiast właściwości zaimplementowanej automatycznie:

public class Bob
{
    private int value;
    public int Value
    { 
        get { return value; } 
        set { this.value = value; }
    }
}

Następnie możesz przekazać pole jako parametr wyjściowy:

Int32.TryParse("123", out bob.value);

Ale oczywiście zadziała to tylko w ramach tej samej klasy, ponieważ pole jest prywatne (i powinno być!).

Nieruchomości po prostu na to nie pozwalają. Nawet w VB, gdzie można przekazać właściwość przez odniesienie lub użyć jej jako parametru out, istnieje w zasadzie dodatkowa zmienna tymczasowa.

Jeśli nie dbałeś o zwracaną wartość TryParse, zawsze możesz napisać własną metodę pomocniczą:

static int ParseOrDefault(string text)
{
    int tmp;
    int.TryParse(text, out tmp);
    return tmp;
}

Następnie użyj:

bob.Value = Int32Helper.ParseOrDefault("123");

W ten sposób możesz użyć jednej zmiennej tymczasowej, nawet jeśli musisz to zrobić w wielu miejscach.

Jon Skeet
źródło
1
Myślę, że problem z pierwszym podejściem polega na tym, że jeśli używasz pola bezpośrednio (zamiast właściwości), możesz omijać reguły walidacji, które mogą istnieć w nieruchomości
Andreas Grech
3
@Jon: Myślę, że chciałbyś zmienić int.Parse na int.TryParse w przykładzie ParseOrDefault.
shahkalpesh
8
Przy okazji, powodem, dla którego nie możesz mieć właściwości jako parametru wyjściowego, jest to, że ustawienie właściwości jest w rzeczywistości wywołaniem funkcji i brakiem przypisania, jeśli spojrzysz pod maskę.
Dirk Vollmar
3
Bardzo chciałbym zobaczyć właściwy cukier składniowy, który pozwoli mi przekazać właściwość jako parametr ref lub out. Zróbmy pracę kompilatorowi, jest szybszy ode mnie.
Ignacio Soler Garcia
1
@SoMoS: To, czy jest to typ wartości, czy nie, nie ma znaczenia dla mojego komentarza. Albo zmiana w metodzie parametru natychmiast zaczyna obowiązywać, albo nie. Wpływa to również na to, co się stanie, jeśli zostanie zgłoszony wyjątek.
Jon Skeet
7

Możesz to osiągnąć, ale nie za pomocą nieruchomości.

public class Bob {
    public int Value { get; set; } // This is a property

    public int AnotherValue; // This is a field
}

Nie możesz używać outdalej Value, ale możesz dalej AnotherValue.

To zadziała

Int32.TryParse("123", out bob.AnotherValue);

Jednak typowe wytyczne mówią, aby nie upubliczniać pola klasowego. Dlatego powinieneś użyć metody zmiennej tymczasowej.

Pierre-Alain Vigeant
źródło