2015-12-31 27 views
12

考慮:爲什麼readonly字段可以通過ref參數修改?

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" 

這怎麼連編譯,仍然工作?我不應該爲構造函數外的_value字段指定一個不同的值,因爲它的標記爲readonly。但是,將它通過ref傳遞給一個方法,它確實可以被操縱。

這是危險的?爲什麼?我感覺不對,但我無法完全理解它。

+0

因爲那永遠不能被寫入只讀值已經存在,它是'default'。一個有用的'readonly'變量*必須至少被寫入一次。不太明顯的細節是字段初始化實際上發生在構造函數中,C#編譯器移動代碼。 –

回答

19

它編譯的原因是您只將值作爲ref參數傳遞給構造函數(允許設置readonly字段)。如果您將呼叫轉移到其他方法Bar(),則會失敗。

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; } 
    } 
} 

上面的代碼提供了一個非常有說服力的編譯器錯誤:

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

+0

非常多。沒有危險,因爲_value在施工後不能修改,也不會在外部暴露(除了您的獲取訪問者) –

+0

謝謝。不知何故,我滑倒了。 :) –

相關問題