2015-12-31 7 views
12

Bedenken Sie:Warum können schreibgeschützte Felder durch Ref-Parameter geändert werden?

class Foo 
{ 
    private readonly string _value; 

    public Foo() 
    { 
     Bar(ref _value); 
    } 

    private void Bar(ref string value) 
    { 
     value = "hello world"; 
    } 

    public string Value 
    { 
     get { return _value; } 
    } 
} 

// ... 

var foo = new Foo(); 
Console.WriteLine(foo.Value); // "hello world" 

Wie wirkt sich das auch kompilieren, dennoch arbeiten? Ich sollte nicht in der Lage sein, dem Feld _value außerhalb des Konstruktors einen anderen Wert zuzuweisen, da dieser mit readonly gekennzeichnet ist. Übergeben Sie es jedoch durch ref an eine Methode, und es kann tatsächlich manipuliert werden.

Ist das gefährlich? Warum? Es fühlt sich falsch an, aber ich kann es nicht genau sagen.

+0

Da ein Nur-Lese-Wert, der nie bereits geschrieben werden kann, existiert, ist es 'default'. Eine nützliche 'readonly'-Variable * muss * mindestens einmal geschrieben werden. Das nicht so offensichtliche Detail ist, dass die Feldinitialisierung tatsächlich im Konstruktor stattfindet, der C# -Compiler den Code verschiebt. –

Antwort

19

Es kompiliert, weil Sie nur den Wert als ref Parameter im Konstruktor übergeben (wobei readonly Felder können festgelegt werden). Wenn Sie Ihren Anruf auf Bar() in eine andere Methode verschoben haben, würde es fehlschlagen.

class Foo 
{ 
    private readonly string _value; 

    public Foo() 
    { 
     Bar(ref _value); 
    } 

    public void Baz() 
    { 
     Bar(ref _value); 
    } 

    private void Bar(ref string value) 
    { 
     value = "hello world"; 
    } 

    public string Value 
    { 
     get { return _value; } 
    } 
} 

Der obige Code liefert einen sehr aufschluss Compiler-Fehler:

A readonly field cannot be passed ref or out (except in a constructor)

+0

ziemlich viel. nicht gefährlich, da _value nach der Konstruktion nicht verändert werden kann und auch nicht extern ausgesetzt wird (abgesehen von Ihrem Zugriff) –

+0

Vielen Dank. Irgendwie ist mir das entglitten. :) –