Считается ли плохой практикой объявлять переменные в свойстве? - PullRequest
3 голосов
/ 20 сентября 2011

У меня есть следующий класс:

public class PeopleInfo
{
   public virtual int ID {get; protected set;}
   public virtual Person Person1 {get;set;}
   public virtual Person Person2 {get;set;}

   public virtual List<Person> People
   {
     get
     {
        var p = new List<Person>();
        p.Add(Person1);
        p.Add(Person2);
        return p;
     }
   }
}

, который я использую с NHibernate.Класс Person используется в качестве компонента, поскольку в таблице PeopleInfo более 1 человека в каждой строке.Идея свойства People () заключается в предоставлении списка только для чтения, который можно зацикливать.Есть ли лучший способ сделать это или это решение считается приемлемым?

Ответы [ 6 ]

11 голосов
/ 21 сентября 2011

Идея свойства People заключается в предоставлении списка только для чтения, который можно зацикливать.Есть ли лучший способ сделать это или это решение считается приемлемым?

Если это ваше намерение, значит, вы его не достигли;Вы предоставили изменяемый список , который можно зациклить.

К счастью, вы каждый раз предоставляете другой изменяемый список, но вы все еще предоставляете изменяемый список.

Я был бы склонен предоставить неизменный список.Есть несколько способов сделать это.Если вы на самом деле предоставляете неизменный список, то у вас есть дополнительное преимущество, заключающееся в том, что список можно вычислять лениво , а затем кэшировать и повторно использовать бесконечно , а не пересоздавать каждый раз, когда вы запрашиваетеit.

Если вам требуется индексированный доступ, я бы создал коллекцию ReadOnlyCollection и обернул ее вокруг одного экземпляра списка, а затем кэшировал и повторно использовал коллекцию только для чтения.Обратите внимание, что если вы изменяете базовый список, коллекция, доступная только для чтения, будет изменяться;это всего лишь только для чтения список, это не неизменный список.

Если вам не требуется индексированный доступ, я бы указал, что возвращая IEnumerable<T>вместо List<T>.Затем вы можете вернуть любую неизменную коллекцию по вашему выбору.

4 голосов
/ 20 сентября 2011

Если это только для чтения, нужно ли это, чтобы он был списком?Вы можете объявить это IEnumerable и сделать:

public virtual IEnumerable<Person> People 
{
    get 
    {
         yield return Person1;
         yield return Person2;
    }
}
3 голосов
/ 20 сентября 2011

Обычно считается, что свойства возвращаются немедленно.Семантически они используются для представления своего рода «состояния» объекта.

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

MSDN также имеет полезную страницу для разработчиков, рассматривающих возможность использования Properties vsМетоды .Перефразируя,

Как правило, методы представляют действия, а свойства представляют данные.

2 голосов
/ 20 сентября 2011

Есть ли лучший способ сделать это или это решение считается приемлемым?

Да, есть лучший способ: сделать это правильно.

public class PeopleInfo {
    public virtual int Id { get; set; }
    public virtual IList<Person> People { get; set; }
}

public class Person {
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual PeopleInfo PeopleInfo { get; set; }
}

public class PeopleInfoMap : ClassMap<PeopleInfo> {
    public PeopleInfoMap() {
        Id(x => x.Id);
        HasMany(x => x.People)
            .Cascade.None()
            .Inverse();
    }
}

public class PersonMap : ClassMap<Person> {
    public PersonMap() {
        Id(x => x.Id);
        Map(x => x.Name);
        References(x => x.PeopleInfo);
    }
}

Ваши таблицы базы данных должны выглядеть следующим образом:

PeopleInfo (Id PK)
Person (Id PK, Name, PeopleInfoId FK PeopleInfo.Id)
1 голос
/ 20 сентября 2011

В этом нет ничего плохого, но ваш пример будет возвращать новый экземпляр с каждым get.Я не уверен, что это то, что вы намерены.

0 голосов
/ 20 сентября 2011

Объявление локальной переменной - это хорошо.Однако есть способ сократить ваш код:

public virtual List<Person> People
{
    get
    {
        return new List<Person> { Person1, Person2 };
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...