Назначение свойству только для чтения в списке инициализаторов

Может кто-нибудь сказать мне, какого черта он компилируется?

namespace ManagedConsoleSketchbook
{
    public interface IMyInterface
    {
        int IntfProp
        {
            get;
            set;
        }
    }

    public class MyClass
    {
        private IMyInterface field = null;

        public IMyInterface Property
        {
            get
            {
                return field;
            }
        }
    }

    public class Program
    {
        public static void Method(MyClass @class)
        {
            Console.WriteLine(@class.Property.IntfProp.ToString());
        }

        public static void Main(string[] args)
        {
            // ************
            // *** Here ***
            // ************

            // Assignment to read-only property? wth?

            Method(new MyClass { Property = { IntfProp = 5 }});
        }
    }
}

person Spook    schedule 03.04.2013    source источник


Ответы (3)


Это инициализатор вложенных объектов. Это описано в спецификации С# 4 следующим образом:

Инициализатор члена, указывающий инициализатор объекта после знака равенства, является инициализатором вложенного объекта, то есть инициализацией внедренного объекта. Вместо присвоения нового значения полю или свойству назначения в инициализаторе вложенных объектов обрабатываются как присвоения членам поля или свойства. Инициализаторы вложенных объектов нельзя применять к свойствам с типом значения или к полям только для чтения с типом значения.

Итак, этот код:

MyClass foo = new MyClass { Property = { IntfProp = 5 }};

будет эквивалентно:

MyClass tmp = new MyClass();

// Call the *getter* of Property, but the *setter* of IntfProp
tmp.Property.IntfProp = 5;

MyClass foo = tmp;
person Jon Skeet    schedule 03.04.2013
comment
Хорошо, теперь это ясно. Однако это запутанный синтаксис. - person Spook; 03.04.2013

Поскольку вы используете инициализатор, который использует установщик ItfProp, не установщик Property.

Таким образом, во время выполнения он выдаст NullReferenceException, поскольку Property все равно будет null.

person bas    schedule 03.04.2013
comment
Можете ли вы уточнить? Как стандарт покрывает эту ситуацию? - person Spook; 03.04.2013
comment
подождите, загружаю визуальную студию, опубликуйте какой-нибудь поясняющий пример - person bas; 03.04.2013
comment
а, Джон дома, я не могу с ним конкурировать :p - person bas; 03.04.2013
comment
@ Spook, не ошибись, Property все равно будет null. - person bas; 03.04.2013

Потому что

int IntfProp {
    get;
    set;
}

не только для чтения.

Вы не вызывали сеттер MyClass.Property, а только геттер.

person Ken Kin    schedule 03.04.2013