2008-08-22 26 views
45

在此之前,C#泛型,每个人都将通过创建一个实现IEnumerable的List <BusinessObject>或BusinessObjectCollection?

IE收藏基础代码为他们的业务对象的集合:

public class CollectionBase : IEnumerable 

,然后将获得从他们的业务对象的集合。

public class BusinessObjectCollection : CollectionBase 

现在使用泛型列表类,是否有人只是使用它呢?我发现,我用的两种技术的妥协:

public class BusinessObjectCollection : List<BusinessObject> 

我这样做是因为我喜欢有强类型的名称,而不是仅仅在绕过列表。

什么是您的方法?

回答

49

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

但是,使用C#3.0中的聚合初始化功能,我会提倡使用自定义集合类的一些新情况。

基本上,C#3.0允许任何类实现IEnumerable,并有一个Add方法来使用新的聚集初始值设定语法。例如,因为字典定义的方法添加(K键,V值),可以初始化一个字典使用此语法:

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

有关功能的最大好处是,它的添加方法与任意数量的论据。例如,鉴于此集合:

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

    //... 
} 

将有可能将其初始化像这样:

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

,如果你需要创建复杂对象的静态表这可能是非常有用的。例如,如果你只是使用List<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<T>

2

如果我需要“增加价值”,我通常只会派生自己的集合类。就像,如果集合本身需要一些“元数据”属性标记。

4

我一直来回在2种选择:

public class BusinessObjectCollection : List<BusinessObject> {} 

或方法,仅仅做到以下几点:

public IEnumerable<BusinessObject> GetBusinessObjects(); 

第一种方法的好处是,你可以改变底层数据存储,而不必混淆方法签名。不幸的是,如果你从一个集合类型继承,这个集合类型从前一个实现中删除一个方法,那么你将不得不在整个代码中处理这些情况。

3

我做的和你乔纳森完全一样......只是从List<T>继承而来。你得到两全其美。但是我通常只在需要添加一些值时才会这样做,比如添加一个LoadAll()方法或其他。

+0

您可以将LoadAll()作为从列表挂起的扩展方法来执行。这会给你LoadAll()每个列表/集合,它可以从任何IEnumerable 读入......有些人可能会说这是滥用扩展方法。但我说它允许你像多重继承一样行事。 – 2009-07-17 18:00:19

+0

好主意,虽然我的LoadAll()方法并不是真正的通用。它根据基础对象类型从不同的表中加载。一般来说,可能有办法做到这一点,但目前我还没有真正考虑过这一点。 – jeremcc 2009-07-24 16:35:08

0

1 6的另一个

无论哪种方式,它同样的事情半打。我只有在有理由将自定义代码添加到BusinessObjectCollection时才会这样做。

无法使用加载方法返回列表允许我在一个通用的泛型类中编写更多的代码并使其正常工作。如Load方法。

9

我更喜欢只使用List<BusinessObject>。键入它只是给代码添加了不必要的样板。 List<BusinessObject>是一种特定类型,它不仅仅是任何List对象,所以它仍然是强类型的。

更重要的是,声明List<BusinessObject>可以让每个阅读代码的人更容易知道他们正在处理的是哪些类型,他们不必搜索以找出BusinessObjectCollection是什么,然后记住它只是一个列表。通过typedefing,你必须要求一个一致的(重新)命名约定,每个人必须遵循才能使其有意义。

3

您应该避免为此创建自己的集合。在重构或添加新功能时,想要多次更改数据结构的类型是很常见的。使用你的方法,你将得到一个独立的类BusinessObjectList,BusinessObjectDictionary,BusinessObjectTree等

我真的没有看到任何值创建这个类只是因为类名更具可读性。是的,尖括号语法有点丑陋,但它在C++,C#和Java中是标准的,所以即使你没有编写使用它的代码,你也会一直运行它。

14

这是recommended,在公共API不使用List <牛逼>,但是使用收集<牛逼>

如果从它虽然继承,你应该罚款,据我所知。

1

我几乎所有的场景都使用泛型列表。我只考虑使用派生集合的唯一时间是如果我添加特定于集合的成员。然而,即便如此,LINQ的出现减少了需求。

-1

这是这样的:

0

正如别人指出的,建议不要公开曝光名单

回报阵列,接受IEnumerable<T>

=),如果你做的FxCop将whinge所以。这包括继承自List:

public MyTypeCollection : List<MyType> 

在大多数情况下,公共API将根据需要公开IList(或ICollection或IEnumerable)。

如果您想要自己的自定义集合,可以通过从Collection继承而不是List继承FxCop。

0

如果我想屏蔽对实际列表的访问权限,我倾向于使用自己的集合来执行此操作。当你写业务对象时,很有可能你需要一个钩子来知道你的对象是否被添加/删除,从这个意义上说,我认为BOCollection是更好的主意。如果这不是必需的,那么List是更轻量级的。另外,如果您需要某种代理(例如,假集合触发数据库的延迟加载),您也可以使用IList检查以提供额外的抽象接口

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

0

在大多数情况下,我只需要使用List方式,因为它在90%的时间内为我提供了所需的所有功能,当需要“额外”时,我从它继承,并且额外的代码。

0

我这样做:

using BusinessObjectCollection = List<BusinessObject>; 

这仅仅是创建一个别名,而不是一个全新的类型。我更喜欢直接使用ListObject> BusinessObjects>,因为它让我可以随时在将来的某个时候更改集合的底层结构,而不必更改使用它的代码(只要我提供相同的属性和方法)即可。

0

试试这个:

System.Collections.ObjectModel.Collection<BusinessObject> 

它使不必要实现基本方法,像做CollectionBase的

2

您可以同时使用。对于懒惰 - 我的意思是生产力 - 列表是一个非常有用的班级,它也是“全面的”,并坦率地充满YANGNI成员。再加上合理的参数/建议提出已经联系有关露出列表作为公共成员的MSDN article,我更喜欢“第三”的方式:

我个人使用Decorator模式揭露只是我从列表IE需要:

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的我们对未来在(我可能更愿意使用一个不同的内部枚举对象,如集合或PERF使用更likley Key Value Pair集合或集合

4

使用类型List<BusinessObject>,您必须声明它们的列表。但是,您返回BusinessObject列表的 ,请考虑返回IEnumerable<T>,IList<T>ReadOnlyCollection<T> - 即返回满足客户端的最弱可能合约。

如果你想“添加自定义代码”到列表中,列表类型上的代码扩展方法。再次,将这些方法附加到最弱的合约,例如

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

当然,你不能,不能与扩展方法添加的状态,因此,如果您需要添加一个新的属性和它背后的一个字段,使用一个子类或更好,一个包装类存储这个。

相关问题