Предположим, что у Вас есть класс Человек:
public class Person
{
public string Name { get; set;}
public IEnumerable Roles {get; set;}
}
Я должен, очевидно, инстанцировать Ролей в конструкторе. Теперь, я раньше делал это со Списком как это:
public Person()
{
Roles = new List();
}
Но я обнаружил этот статический метод в System.Linq
пространство имен
IEnumerable Enumerable.Empty();
Из MSDN:
Empty(TResult)()
метод кэширует пустую последовательность типаTResult
. Когда объект, который это возвращает, перечисляется, это не приводит ни к каким элементам.В некоторых случаях этот метод полезен для передачи пустой последовательности к пользовательскому методу, который берет
IEnumerable(T)
. Это может также использоваться для генерации нейтрального элемента для методов такой какUnion
. Посмотрите раздел Example для примера этого использования
Таким образом, лучше записать конструктору как этот? Вы используете его? Почему? или в противном случае Почему нет?
public Person()
{
Roles = Enumerable.Empty();
}
Предполагая, что вы действительно хотите каким-то образом заполнить свойство Roles
, затем инкапсулируйте это, сделав его установщик приватным и инициализируя его новым списком в конструкторе:
public class Person
{
public string Name { get; set; }
public IList<Role> Roles { get; private set; }
public Person()
{
Roles = new List<Role>();
}
}
Если вы действительно действительно хотите иметь публичный установщик ,оставьте Роли
со значением null
и избегайте выделения объекта.
Проблема с вашим подходом заключается в том, что вы не можете добавлять какие-либо элементы в коллекцию - я бы имел частную структуру, например список, а затем выставлял бы элементы как Enumerable:
public class Person
{
private IList<Role> _roles;
public Person()
{
this._roles = new List<Role>();
}
public string Name { get; set; }
public void AddRole(Role role)
{
//implementation
}
public IEnumerable<Role> Roles
{
get { return this._roles.AsEnumerable(); }
}
}
Если вы намерен какой-то другой класс создать список ролей (что я бы не рекомендовал), тогда я бы вообще не инициализировал перечислимое в Person.
Типичная проблема с раскрытием закрытого списка как IEnumerable заключается в том, что клиент вашего класса может вмешаться в него путем преобразования типов. Этот код будет работать:
var p = new Person();
List<Role> roles = p.Roles as List<Role>;
roles.Add(Role.Admin);
Вы можете избежать этого, реализовав итератор:
public IEnumerable<Role> Roles {
get {
foreach (var role in mRoles)
yield return role;
}
}
Я думаю, что Enumerable.Empty
лучше, потому что он более ясен: ваш код ясно указывает на ваши намерения. Он также может быть немного более эффективным, но это лишь второстепенное преимущество.
Более серьезной проблемой здесь будет раскрытие ролей
как публичного поля .
выглядит лучше:
public class Person
{
public string Name { get; set; }
private List<Role> _roles = null;
public IEnumerable<Role> Roles
{
get {
if (_roles != null)
return _roles;
else
return Enumerable.Empty<Role>();
}
}
}
И, возможно, вам стоит попробуйте вернуть его как ReadonlyCollection , в зависимости от того, как вы хотите его использовать.
И Enumerable.Empty здесь не лучше
, просто немного эффективнее, когда роли обычно остаются пустыми.