在属性中声明变量被认为是不好的做法吗?

时间:2011-09-20 19:19:59

标签: c# nhibernate

我有以下课程:

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 个答案:

答案 0 :(得分:11)

  

People属性背后的想法是提供一个可以循环的只读列表。有更好的方法可以做到这一点,还是认为这个解决方案可以接受?

如果这是你的意图那么你还没有实现它;你提供了一个可以循环的可变列表

幸运的是,您每次都提供不同的可变列表,但您仍然提供可变列表。

我倾向于提供一个不可变的列表。有很多方法可以做到这一点。如果您实际提供了一个不可变列表,那么您还可以获得额外的好处,即列表可以懒惰地计算然后缓存并无限期地重复使用而不是每次都重新构建要求它。

如果您需要索引访问,那么我将创建一个ReadOnlyCollection并将其包装在列表的单个实例周围,然后缓存并重新使用只读集合。请注意,如果您改变基础列表,则只读集合将显示为mutate;它只是一个只读列表,它不是不可变列表。

如果您不需要编入索引,那么我会通过返回IEnumerable<T>而不是List<T>来表示。然后,您可以返回您选择的任何不可变集合。

答案 1 :(得分:4)

如果它是只读的,你需要它作为一个列表吗?您可以将其声明为IEnumerable并执行:

public virtual IEnumerable<Person> People 
{
    get 
    {
         yield return Person1;
         yield return Person2;
    }
}

答案 2 :(得分:3)

通常假定属性按惯例立即返回。从语义上讲,它们用于表示对象的某种“状态”。

你当然不应该在属性中进行任何长时间的计算。因此,它在很大程度上取决于上下文是否适合声明变量。一般情况下,它没有问题,但由于其计算强度,动态生成列表可能

对于考虑使用Properties vs. Methods的开发人员,MSDN也有一个有用的页面。换句话说,

  

通常,方法表示操作,属性表示数据。

答案 3 :(得分:2)

  

有更好的方法可以做到这一点,还是认为这个解决方案可以接受?

是的,有更好的方法:做得对。

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)

答案 4 :(得分:1)

它没有任何问题,但是你的示例将返回每个get的新实例。我不确定这是不是你想要的。

答案 5 :(得分:0)

声明一个局部变量很好。但是,有一种缩短代码的方法:

public virtual List<Person> People
{
    get
    {
        return new List<Person> { Person1, Person2 };
    }
}