2015-12-31 2 views
12

Рассмотрим:Почему поля только для чтения могут быть изменены с помощью параметров 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

Спасибо. Как-то это проскользнуло мимо меня. :) –