清单VS IEnumerable的私人,延迟加载特性(List vs IEnumerable in

2019-10-19 05:39发布

我有一个公共属性(AllCustomers),它是由私有财产的延迟加载支持。

据我所知,公共财产应该是IEnumerable的( “程序接口,而不是实现” )。

不过,我可以看到两种方式来构建私有财产。

第一个选择,与私人列表 -

private List<Customer> _AllCustomers;
public IEnumerable<Customer> AllCustomers
{
    get
    {
        if (_AllCustomers == null)
        {
            _AllCustomers = DAL.GetAllCustomers().ToList(); 
        }
        return _AllCustomers;
    }
}

第二个选项,其中私人IEnumerable-

private IEnumerable<Customer> _AllCustomers;
public IEnumerable<Customer> AllCustomers
{
    get
    {
        if (_AllCustomers == null)
        {
            _AllCustomers = DAL.GetAllCustomers(); 
        }
        return _AllCustomers;
    }
}

我觉得第一个选项出现更正确的,因为它会一度创出数据库和存储结果,而第二个将导致多个数据库命中。

我的问题是 -

  • 我在我的分析是正确的?
  • 什么是不同方法的含义是什么?
  • 有没有第二个选择将是首选的任何时候?
  • 有没有更好的,更地道的方式表达了第二个选项?

Answer 1:

这里涉及到“懒惰”的几个层次。 一个是固有的懒惰IEnumerable实现,另一种是懒惰实现你自己添加到您的财产。

你的第一个实现将访问数据库一次,第一次AllCustomers访问。 它将构建查询GetAllCustomers并执行它,当你调用ToList ,本地存储的结果。

你的第二个实施将访问数据库只有一次(假设你的LINQ的实现是半路出家)。 然而,这将是于第一个场景-甚至称您AllCustomer属性将只返回一个IQueryable ,当这只会进行AllCustomers实际上访问或枚举。 这可能会立即之后,或不 - 这是一个懒惰的实现。 同样,假设你的LINQ提供程序是不是太傻了,遍历整个集合将仍然只打了DB一次。

你为什么要选择第一个选项呢? 因为(再次,取决于实现),遍历AllCustomers 两次会打的DB两次。 ReSharper的,够方便,警告我们,当我们有一个可能的多个枚举IEnumerable 。 在本地存放List将确保我们保持一个缓存的本地副本。 为了确保这在代码中明确表示,考虑曝光的IReadOnlyList代替的IEnumerable



Answer 2:

双方将打DB只有一次作为_AllCustomers支持字段只有NULL当调用getter时首次。

随着个人喜好的问题,我通常喜欢IEnumerable在我的界面和方法的声明,但是支持领域是具体的类,如List<stuff> 。 使事情变得像修改您的收藏除其他更容易。



Answer 3:

据我所知,公共财产应该是IEnumerable的(“程序接口,而不是实现”)。

这种认识是错误的。 规划在接口原则不说你应该编程, 哪个接口。 在你的榜样。 我会暴露IList<T>并使其只读假设你不希望消费者修改列表:

private List<Customer> _AllCustomers;
public IList<Customer> AllCustomers
{
    get
    {
        if (_AllCustomers == null)
        {
            _AllCustomers = DAL.GetAllCustomers().ToList().AsReadOnly(); 
        }
        return _AllCustomers;
    }
}


文章来源: List vs IEnumerable in private, lazy-loaded property