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

Это опасно? Зачем? Мне это кажется нехорошим, но я не могу на него положиться.

Ответ 1

Он компилируется, потому что вы передаете значение только как параметр 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; }
    }
}

Приведенный выше код обеспечивает очень важную ошибку компилятора:

Поле readonly нельзя передать ref или out (кроме конструктора)