Подтвердить что ты не робот

Инициализация объекта С# только свойств коллекции только для чтения

В моей жизни я не могу понять, что происходит в примере куба кода С# ниже. Свойство collection (List) тестового класса задается как только для чтения, но все же я могу, по-видимому, назначить его в инициализаторе объекта.

** EDIT: Исправлена ​​проблема с List 'getter'

using System;
using System.Collections.Generic;
using NUnit.Framework;

namespace WF4.UnitTest
{
    public class MyClass
    {
        private List<string> _strCol = new List<string> {"test1"};

        public List<string> StringCollection 
        {
            get
            {
                return _strCol;
            }
        }
    }

    [TestFixture]
    public class UnitTests
    {
        [Test]
        public void MyTest()
        {
            MyClass c = new MyClass
            {
                // huh?  this property is read only!
                StringCollection = { "test2", "test3" }
            };

            // none of these things compile (as I wouldn't expect them to)
            //c.StringCollection = { "test1", "test2" };
            //c.StringCollection = new Collection<string>();

            // 'test1', 'test2', 'test3' is output
            foreach (string s in c.StringCollection) Console.WriteLine(s);
        }
    }
}
4b9b3361

Ответ 1

Это:

MyClass c = new MyClass
{
    StringCollection = { "test2", "test3" }
};

преобразуется в это:

MyClass tmp = new MyClass();
tmp.StringCollection.Add("test2");
tmp.StringCollection.Add("test3");
MyClass c = tmp;

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

Это описано более подробно в разделе 7.6.10.3 спецификации С# 4.

РЕДАКТИРОВАТЬ: Как точка интереса, я был немного удивлен, что он дважды называет геттер. Я ожидал, что он вызовет геттер один раз, а затем дважды вызовет Add... спецификация включает пример, который демонстрирует это.

Ответ 2

Вы не вызываете сеттер; вы по существу вызываете c.StringCollection.Add(...) каждый раз (для "test2" и "test3" ) - это инициализатор коллекции. Для того чтобы это было присвоение свойства, это было бы:

// this WON'T work, as we can't assign to the property (no setter)
MyClass c = new MyClass
{
    StringCollection = new StringCollection { "test2", "test3" }
};

Ответ 3

Я думаю, что, если читать только, вы не можете делать

c.StringCollection = new List<string>();

Но вы можете назначить элементы для списка...
Я не прав?

Ответ 4

Свойство StringCollection не имеет настройки, поэтому, если вы не добавите его, вы не сможете изменить его значение.