C# 检查延迟加载的属性是否已实例化

C# 检查延迟加载的属性是否已实例化,c#,lazy-loading,C#,Lazy Loading,在具有延迟加载属性的类中,例如: private Collection<int> someInts; public Collection<int> SomeInts { get { if (this.someInts == null) this.someInts = new Collection<int>(); return this.someInts; } } 然后使用该属性。。例如: if (th

在具有延迟加载属性的类中,例如:

private Collection<int> someInts;

public Collection<int> SomeInts
{
    get
    {
        if (this.someInts == null) this.someInts = new Collection<int>();
        return this.someInts;
    }
}
然后使用该属性。。例如:

if (thatClass.SomeIntsExist)
{
    // do something with thatClass.SomeInts collection
}
或者这是过早的优化。使用下面这样的东西当然更容易,但它将不必要地实例化集合:

if (thatClass.SomeInts.Count > 0)
{
    // do something with thatClass.SomeInts collection
}

编译器是否足够聪明,能够解决这样的问题?有更好的方法吗?

如果延迟加载的类很大,初始化需要一些时间。。。。这样的布尔值很有意义


在我看来,对于一个简单的.net集合来说,它没有什么意义

编译器不会自动计算出这样的结果。 也就是说,在最后一种情况下

if (thatClass.SomeInts.Count > 0) 
{ 
    // do something with thatClass.SomeInts collection 
} 
集合将被实例化


因此,在我看来,这取决于初始化集合的成本有多高——在简单的情况下,这并不是非常昂贵,但浪费的内存可能会加起来……

即使延迟初始化属性听起来也像是过早优化。我能想到的只有极少数情况下延迟创建空集合有助于解决问题(假设您的示例没有过度简化)


但是,当您必须延迟集合初始化时,您可能也应该(甚至必须)优化
Exists
方法,因为延迟初始化是一项关键要求。

如果您要处理昂贵的数据检索(例如数据库查询),那么拥有这样的属性是值得的


但是,您的代码中有一个缺陷
SomeIntsExist
只有在事先访问了属性的情况下才会给出正确的答案,如果属性是延迟加载的,那么可能确实存在整数,但它们只是还没有加载而已。应该将其重命名为类似于
IsInitialized
。我知道这是一个例子,但可能仍然值得指出:)

我没有看懂你的第二段。仅当集合已实例化且包含项时,SomeIntsExist属性才会返回true,对吗?我猜你的意思是,如果它被多个线程访问,这可能是个问题?@Paul:我假设你访问它时会加载你的列表(正如你提到的lazy-loaded属性)。但是,再次查看您的代码时,您懒得初始化属性,在这个特定场景中,除非您明确需要检查属性是否已初始化,否则不会为您带来任何好处。感谢您的澄清,并为我混乱的术语表示歉意!顺便说一下,您的代码不是线程安全的。多个线程可能同时发现backing字段为null,并且每个线程创建一个空集合。因此,后续代码可能会使用线程A创建的集合一段时间,直到线程B再次用空集合覆盖它。如果你需要线程安全,你必须使用某种形式的锁定。@Daniel,谢谢-评论不错。我知道这些问题,但尽量保持示例的简单:)。@Daniel“顺便说一句,您的代码不是线程安全的”。大多数框架类的实例成员都不是线程安全的,所以这并不奇怪。事实上,我认为将线程安全留给类的用户通常是最佳实践。
if (thatClass.SomeInts.Count > 0) 
{ 
    // do something with thatClass.SomeInts collection 
}