IList <t> </t>的默认getter

时间:2014-05-06 12:11:35

标签: c# class properties

我已经开始构建一个C#应用程序了,我的眼中有点刺痛:

我的大多数课程都有很多属性,例如:

private IList<Address> _addresses;
private IList<Phone> _phones;

public virtual IList<Address> Addresses
{
    get
    {
        if (_addresses == null)
            _addresses = new List<Address>();
        return _addresses;
    }
    set { _addresses = value; }
}
public virtual IList<Phone> Phones
{
    get
    {
        if (_phones == null)
            _phones = new List<Phone>();
        return _phones;
    }
    set { _phones = value; }
}

我想知道,有没有办法在一个地方定义这种行为(具体来说,默认的getter),并重用它?我应该以某种方式延长IList吗?

就像我可以使用

一样
public virtual string Temp { get; set; }

而不是:

private string _temp;
public virtual string Temp
{
    get { return _temp; }
    set { _temp = value; }
}

5 个答案:

答案 0 :(得分:4)

您可以使用List<T>完全使用string。您可能遇到的问题是,在两种情况下,属性都是null,直到您为getter分配一个值,即if语句。

您将无法通过扩展IList来解决此问题。

您可以初始化支持字段:

private IList<Thing> _things = new List<Thing>();

在C#的下一个版本中,您实际上可以以相同的方式初始化自动属性。语法需要一点时间习惯:

public IList<Thing> Things { get; set; } = new List<Thing>();

您还可以在getter中使用此语法在第一次调用getter时初始化集合:

get { return _things ?? (_things = new List<Thing()); }

最后,您可以在构造函数中将值分配给自动属性。这可能更容易出错,因为声明和赋值没有可见的连接。

答案 1 :(得分:3)

目前最短的方法是:

public static List<int> _list;

public static List<int> List
{
    get { return _list ?? (_list = new List<int>()); }
    set { _list = value; }
}

如果它是_list,则初始化null,否则返回_list字段。

答案 2 :(得分:2)

您可以初始化字段:

private IList<Address> _addresses = new List<Address>();
private IList<Phone> _phones= new List<Phone>();

或者在构造函数中设置属性:

//constructor
public MyClass()
{
    Addresses = new List<Address>();
    Phones = new List<Phone>();
}

但这些与您的代码完全相同。在您的情况下,如果从未调用过属性,则永远不会初始化它们。

答案 3 :(得分:2)

在不幸的C#6中,您可以执行以下操作:

public virtual IList<Address> Addresses { get; set; } = new List<Address>(); 
public virtual IList<Phone> Phones { get; set; } = new List<Phone>();

现在你可以使用自动属性和默认的构造来缩短它:

public virtual IList<Address> Addresses { get; set; }; 
public virtual IList<Phone> Phones { get; set; };

public CLASS()
{
    Addresses = new List<Address>();
    Phones = new List<Phone>()
}

注意:两种解决方案都会立即初始化列表,而不是首次访问。如果不需要,我想你可以使用PostSharp来做这些事情。

  

我应该以某种方式扩展IList吗?

这对于&#34;非初始化字段&#34;的情况没有帮助。你的自定义实现甚至不会#34;还有#34;。

答案 4 :(得分:1)

我会在等待C#6时创建一个静态辅助函数,这就是它在我选择的MVVM框架中的完成方式。我认为这是一个相当普遍的实现,可以添加更多的重载来处理极端情况。

public static class PropertyHelper
{
    public static T Get<T, U>(ref T backingField, U initialValue = null)
        where T : class
        where U : class, T, new()
    {
        initialValue = initialValue ?? new U();
        return backingField ?? (backingField = initialValue);
    }
}

public class MyClass
{
    private IList<int> myVar;

    public IList<int> MyProperty
    {
        get { return PropertyHelper.Get<IList<int>, List<int>>(ref myVar); }
        set { myVar = value; }
    }

    private IList<int> myVar2;

    public IList<int> MyProperty2
    {
        get { return PropertyHelper.Get(ref myVar2, new List<int>()); }
        set { myVar2 = value; }
    }
}