Инициализатор объекта C # будет инициализировать свойства только для чтения, но только для не примитивных типов - PullRequest
3 голосов
/ 01 мая 2019

В следующем тестовом коде я не понимаю, почему первая строка TestMethod допустима, а остальные две строки - нет:

public class Bar
{
    public string Prop { get; set; }
}

public class Foo
{

    public int Primitive { get; } = 0;
    public Func<int, int> Function { get; } = (i) => i;
    public Bar Bar { get; } = new Bar();

}

public class TestClass
{
    public void TestMethod()
    {
        var baz = new Foo { Bar = { Prop = "Hello World!" } }; // legal
        var buzz = new Foo { Primitive = 1 }; // Property or indexer 'Foo.Primitive' cannot be assigned to -- it is read only
        var fuzz = new Foo { Function = (i) => 2 }; // Property or indexer 'Foo.Function' cannot be assigned to -- it is read only
    }
}

Если разрешено присваивать объекту только для чтения свойства типа класса, такие как Bar, в инициализаторе объекта (что это такое; и это имеет смысл, поскольку «только чтение» действительно означает «только чтение», кроме как во время создания класса ») в C #, как я понимаю), тогда почему запрещено присваивать свойства с такими типами, как int и Func<int, int>?

Это кажется еще более запутанным, поскольку (опять же, насколько я понимаю) Func<int, int> является ссылочным типом, подобно свойству Bar, но в отличие от свойства int.

Ответы [ 2 ]

4 голосов
/ 01 мая 2019
var baz = new Foo { Bar = { Prop = "Hello World!" } }; // legal

Это не назначение на Bar. Это по сути:

var tmp = new Foo();
tmp.Bar.Prop = "Hello World!";
var baz = tmp;

Ни в коем случае не присвоено .Bar.

И наоборот:

var buzz = new Foo { Primitive = 1 };

является:

var tmp = new Foo();
tmp.Primitive = 1;
var buzz = tmp;

который назначает для .Primitive.

3 голосов
/ 01 мая 2019

Если разрешено присваивать объекту только для чтения свойства типа класса, такие как Bar, в инициализаторе объекта (которым он является [...])

Нет, это не так. Инициализаторы объектов вызывают конструктор, а затем присваивают его свойствам. Например, этот код:

var buzz = new Foo { Primitive = 1 };

это просто синтаксический сахар для этого:

var buzz = new Foo();
buzz.Primitive = 1;

Это недопустимо, если Primitive - свойство только для чтения.

(Чтобы быть очень педантичным, более уместно рассматривать его как присвоение временной локальной переменной, задание свойств, а затем присвоение buzz в самом конце, но мы пока проигнорируем это.)

Код, который вы наблюдали за работой, не устанавливает эти свойства только для чтения - он получает их, а затем устанавливает значения, используя возвращенную ссылку. Итак, это:

var baz = new Foo { Bar = { Prop = "Hello World!" } }

фактически эквивалентно:

var baz = new Foo();
baz.Bar.Prop "Hello World!";

Это полностью верно, даже если Bar только для чтения.

...