0

从访问器返回新实例是否存在问题?如果是这样,有没有更好的方法?

public class Person
{
    private RecIpDet _ipDet;
    public RecIpDet IpDet
    {
        get 
        {                 
            if(_ipDet == null)
                _ipDet = new RecIpDet();
            return _ipDet; 
        }
    } 
}
4

5 回答 5

5

存在问题,因为您从未设置字段,因此每次调用该属性时都会返回一个新对象。

你应该设置_ipDet它是否为空,然后返回它。这称为延迟实例化或延迟初始化

public class Person
{
    private RecIpDet _ipDet;

    public RecIpDet IpDet
    {
        get 
        {                 
            if (_ipDet == null)
            {
                _ipDet = new RecIpDet();
            }

            return _ipDet; 
        }
    } 
}

请记住,这不是线程安全的,所以如果这对您来说是一个因素,您将需要一个更强大的机制。对于单线程应用程序,这种惰性实例化方法很好。

如果您使用的是 .NET 4.0 或更高版本,则可以使用Lazy<T>我认为是线程安全的类:

public class Person
{
    private Lazy<RecIpDet> _ipDet = new Lazy<RecIpDet>(() => new RecIpDet());

    public RecIpDet IpDet
    {
        get 
        {                 
            return _ipDet.Value; 
        }
    } 
}
于 2012-10-02T14:09:42.937 回答
5

对我们来说,通常的做法是使用:

get
{
    return _ipDet ?? (_ipDet = new RecIpDet());
}
于 2012-10-02T14:12:46.187 回答
2

根据您的评论,您似乎确实打算设置实例,所以这是一个很好的延迟实例化的经典示例(尽管不是线程安全的)。如果您不需要担心线程安全,那么无论如何这将起作用:

get
{
    if (_ipDet == null)
        _ipDet = new RecIpDet();

    return _ipDet
}

但是,如果您使用的是 .NET 4.0,我建议您Lazy<T>不要构建自己的惰性构造:

public class Person
{
    private Lazy<RecIpDet> _ipDet = new Lazy<RecIpDet>();

    public RecIpDet IpDet
    {
        get { return _ipDet.Value; }
    } 
}

Lazy 的 Value 在第一次调用时调用该类型的构造函数,并且是线程安全的(您可以选择不同的)线程安全级别。

于 2012-10-02T14:09:55.287 回答
1

到目前为止,您将始终返回一个新对象。除非以某种方式 _ipDet 被设置为一个值。这使您的代码表现得非常不可预测。要么实现单例模式并替换 return new RecIpDet(); with _ipDet = new RecIpDet(); 或者让它总是返回一个新对象,这很好。

于 2012-10-02T14:12:29.037 回答
0

使用Lazy Instantiation是很不寻常的,大多数时候它是用于Singleton模式,在这里你可以找到更多信息:

实现单例模式

在此页面中,您甚至可以找到一种使其成为线程安全的方法。

它对于可以从应用程序中的任何位置访问的全局对象非常有用。

于 2012-10-02T14:19:22.490 回答