Инициализация объекта С# только свойств коллекции только для чтения
В моей жизни я не могу понять, что происходит в примере куба кода С# ниже. Свойство 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);
}
}
}
Ответы
Ответ 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
не имеет настройки, поэтому, если вы не добавите его, вы не сможете изменить его значение.