List <BusinessObject>还是BusinessObjectCollection?

时间:2020-03-05 18:41:53  来源:igfitidea点击:

在Cgenerics之前,每个人都将通过创建实现IEnumerable的集合库来为其业务对象编码集合

IE:

public class CollectionBase : IEnumerable

然后从中派生其业务对象集合。

public class BusinessObjectCollection : CollectionBase

现在有了通用列表类,是否有人会使用它呢?我发现我使用了两种技术的折衷方案:

public class BusinessObjectCollection : List<BusinessObject>

之所以这样做,是因为我喜欢使用强类型的名称,而不仅仅是传递列表。

你的方法是什么?

解决方案

回答

通常,只有在需要"增加价值"时,我才派生自己的收藏类。就像,如果集合本身需要带有一些"元数据"属性标记。

回答

我一直在来回选择2个选项:

public class BusinessObjectCollection : List<BusinessObject> {}

或者仅执行以下操作的方法:

public IEnumerable<BusinessObject> GetBusinessObjects();

第一种方法的好处是我们可以更改基础数据存储,而不必弄乱方法签名。不幸的是,如果我们继承的集合类型从以前的实现中删除了一个方法,那么我们将不得不在整个代码中处理这些情况。

回答

我和我们乔纳森(Jonathan)完全一样...只是从List &lt;T>继承而来。我们将两全其美。但是我通常只在有一些值要添加时才这样做,例如添加LoadAll()方法或者其他方法。

回答

1个中的6个,另外六个

无论哪种方式都是一样的。仅当我有理由将自定义代码添加到BusinessObjectCollection中时,才执行此操作。

有了它,就没有了使用load方法返回的列表,这使我可以在一个通用的泛型类中编写更多代码并使其工作。如Load方法。

回答

我更喜欢只使用List &lt;BusinessObject>。类型化它只是在代码中添加了不必要的样板。 List <BusinessObject>是一种特定的类型,它不仅是任何List对象,因此仍具有强类型。

更重要的是,声明List &lt;BusinessObject>可以使每个阅读代码的人都更轻松地知道他们正在处理的类型,他们不必搜索以找出BusinessObjectCollection是什么,然后记住只是一个清单。通过类型定义,我们必须要求每个人都必须遵循一个一致的(重新)命名约定才能使之有意义。

回答

我们可能应该避免为此目的创建自己的集合。在重构期间或者添加新功能时,几次更改数据结构的类型是很常见的。使用方法,我们将获得一个单独的类,用于BusinessObjectList,BusinessObjectDictionary,BusinessObjectTree等。

我仅仅在创建类时并没有看到任何价值,只是因为类名更具可读性。是的,尖括号语法有点丑陋,但这是C ++和Cand Java中的标准语法,因此即使我们不编写使用它的代码,也总是会遇到这种情况。

回答

建议在公共API中不要使用List <T>,而要使用Collection <T>

如果我们从它继承,那么我们应该没问题,afaik。

回答

通常,我通常只是直接使用List,除非出于某种原因我需要封装数据结构并提供其功能的有限子集。这主要是因为如果我对封装没有特别的要求,那么这样做只会浪费时间。

但是,借助C3.0中的聚合初始化功能,在某些新情况下,我会提倡使用定制的收集类。

基本上,C3.0允许任何实现" IEnumerable"并具有Add方法的类使用新的聚合初始化程序语法。例如,由于Dictionary定义了方法Add(K key,V value),因此可以使用以下语法初始化字典:

var d = new Dictionary<string, int>
{
    {"hello", 0},
    {"the answer to life the universe and everything is:", 42}
};

该功能的优点在于,它可用于带有任意数量参数的add方法。例如,给定此集合:

class c1 : IEnumerable
{
    void Add(int x1, int x2, int x3)
    {
        //...
    }

    //...
}

可以像这样初始化它:

var x = new c1
{
    {1,2,3},
    {4,5,6}
}

如果我们需要创建复杂对象的静态表,这将非常有用。例如,如果我们只使用List &lt;Customer>,并且想创建一个客户对象的静态列表,则必须像这样创建它:

var x = new List<Customer>
{
    new Customer("Scott Wisniewski", "555-555-5555", "Seattle", "WA"),
    new Customer("John Doe", "555-555-1234", "Los Angeles", "CA"),
    new Customer("Michael Scott", "555-555-8769", "Scranton PA"),
    new Customer("Ali G", "", "Staines", "UK")
}

但是,如果我们使用自定义集合,例如:

class CustomerList  : List<Customer>
{
    public void Add(string name, string phoneNumber, string city, string stateOrCountry)
    {
        Add(new Customer(name, phoneNumber, city, stateOrCounter));
    }
}

然后,我们可以使用以下语法初始化集合:

var customers = new CustomerList
{
    {"Scott Wisniewski", "555-555-5555", "Seattle", "WA"},
    {"John Doe", "555-555-1234", "Los Angeles", "CA"},
    {"Michael Scott", "555-555-8769", "Scranton PA"},
    {"Ali G", "", "Staines", "UK"}
}

这具有易于键入和易于阅读的优点,因为它们不需要为每个元素重新键入元素类型名称。如果元素类型很长或者很复杂,则此优势可能会特别强大。

话虽如此,这仅在我们需要在应用程序中定义的静态数据收集时有用。某些类型的应用程序(例如编译器)一直在使用它们。诸如典型的数据库应用程序之类的其他应用程序则不是,因为它们从数据库加载了所有数据。

我的建议是,如果我们需要定义对象的静态集合,或者需要封装掉集合接口,然后创建一个自定义集合类。否则,我将直接使用List &lt;T>

回答

我几乎在所有情况下都使用通用列表。我唯一会考虑使用派生集合的时间是,如果我添加集合特定成员。但是,LINQ的出现减少了对此的需求。

回答

这是这样的:

返回数组,接受IEnumerable &lt;T>

=)

回答

正如其他人指出的那样,建议不要公开公开List,如果这样做,FxCop会发牢骚。这包括从List继承,如:

public MyTypeCollection : List<MyType>

在大多数情况下,公共API会适当地公开IList(或者ICollection或者IEnumerable)。

如果我们想要自己的自定义集合,则可以通过从Collection继承而不是List来使FxCop保持安静。

回答

如果选择创建自己的集合类,则应在System.Collections.ObjectModel命名空间中检出类型。

命名空间定义了基础类,使实现者可以更轻松地创建自定义集合。

回答

如果我想屏蔽对实际列表的访问,则倾向于使用自己的收藏集来进行。在编写业务对象时,很有可能需要一个钩子才能知道是否要添加/删除对象,从这种意义上讲,我认为BOCollection是更好的主意。如果不需要,那么List更轻巧。另外,如果我们需要某种代理(例如,虚假集合会触发数据库的延迟加载),则可能需要检查使用IList来提供其他抽象接口。

但是...为什么不考虑Castle ActiveRecord或者任何其他成熟的ORM框架? :)

回答

在大多数情况下,我只是简单地使用List方法,因为它为我提供了90%的时间所需的所有功能,并且当需要"多余"的东西时,我会从中继承并编码更多的东西。

回答

我会这样做:

using BusinessObjectCollection = List<BusinessObject>;

这只会创建一个别名,而不是一个全新的类型。我更喜欢直接使用List <BusinessObject>,因为它使我可以在将来的某个时候自由更改集合的基础结构,而无需更改使用它的代码(只要我提供相同的属性和方法)。

回答

试试这个:

System.Collections.ObjectModel.Collection<BusinessObject>

它不需要像CollectionBase这样的基本方法

回答

我们可以同时使用。对于懒惰,我的意思是生产率列表是一个非常有用的类,它也是"综合性的",并且坦率地说是由YANGNI成员组成的。再加上已经链接有关将List公开为公众成员的MSDN文章提出的明智的论点/建议,我更喜欢"第三种"方式:

就个人而言,我使用装饰器模式仅显示列表中需要的内容,即:

public OrderItemCollection : IEnumerable<OrderItem> 
{
    private readonly List<OrderItem> _orderItems = new List<OrderItem>();

    void Add(OrderItem item)
    {
         _orderItems.Add(item)
    }

    //implement only the list members, which are required from your domain. 
    //ie. sum items, calculate weight etc...

    private IEnumerator<string> Enumerator() {
        return _orderItems.GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }    
}

更进一步,我可能会将OrderItemCollection抽象到IOrderItemCollection中,以便将来在以后交换我的IOrderItemCollection实现(我可能更喜欢使用其他内部可枚举的对象,例如Collection或者更多的likley来使性能使用键值对集合或者Set 。

回答

使用`List <BusinessObject>'类型,在其中必须声明它们的列表。然而,
如果要返回" BusinessObject"的列表,请考虑返回" IEnumerable <T>"," IList <T>"或者" ReadOnlyCollection <T>",即返回满足客户要求的最弱合同。

要在列表中"添加自定义代码"的地方,列表类型上的代码扩展方法。同样,将这些方法添加到最弱的合约上,例如

public static int SomeCount(this IEnumerable<BusinessObject> someList)

当然,我们不能也不应使用扩展方法添加状态,因此,如果我们需要在其后添加新属性和字段,请使用子类或者更好的包装类来存储此属性。