Lista o BusinessObjectCollection?


Antes de los genéricos de C#, todos codificaban colecciones para sus objetos de negocio creando una base de colecciones que implementabaerableumerable

IE:

public class CollectionBase : IEnumerable

Y luego derivarían sus colecciones de Objetos de Negocio de eso.

public class BusinessObjectCollection : CollectionBase

Ahora con la clase genérica list, ¿alguien usa eso en su lugar? He encontrado que uso un compromiso de las dos técnicas:

public class BusinessObjectCollection : List<BusinessObject>

Hago esto porque me gusta tener nombres fuertemente escritos en lugar de simplemente pasar Listas alrededor.

¿Cuál es su enfoque?

Author: Mark Biek, 2008-08-22

18 answers

Generalmente estoy en el campo de solo usar una Lista directamente, a menos que por alguna razón necesite encapsular la estructura de datos y proporcionar un subconjunto limitado de su funcionalidad. Esto es principalmente porque si no tengo una necesidad específica de encapsulación, entonces hacerlo es solo una pérdida de tiempo.

Sin embargo, con la función aggregate initializes en C# 3.0, hay algunas situaciones nuevas en las que recomendaría el uso de clases de colección personalizadas.

Básicamente, C # 3.0 permite cualquier clase que implementa IEnumerable y tiene un método Add para usar la nueva sintaxis del inicializador aggregate. Por ejemplo, como Dictionary define un método Add (clave K, valor V) es posible inicializar un diccionario usando esta sintaxis:

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

Lo bueno de la característica es que funciona para agregar métodos con cualquier número de argumentos. Por ejemplo, dada esta colección:

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

    //...
}

Sería posible inicializarlo así:

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

Esto puede ser realmente útil si necesidad de crear tablas estáticas de objetos complejos. Por ejemplo, si solo estuviera usando List<Customer> y quisiera crear una lista estática de objetos de cliente, tendría que crearla de la siguiente manera:

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")
}

Sin embargo, si usas una colección personalizada, como esta:

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

Entonces podría inicializar la colección usando esta sintaxis:

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"}
}

Esto tiene la ventaja de ser más fácil de escribir y más fácil de leer porque no es necesario volver a escribir el nombre del tipo de elemento para cada elemento. La ventaja puede ser particularmente fuerte si el tipo de elemento es largo o complejo.

Dicho esto, esto solo es útil si necesita colecciones estáticas de datos definidas en su aplicación. Algunos tipos de aplicaciones, como los compiladores, las usan todo el tiempo. Otras, como las aplicaciones de base de datos típicas, no lo hacen porque cargan todos sus datos de una base de datos.

Mi consejo sería que si necesita definir una colección estática de objetos, o necesita encapsular la colección interfaz, a continuación, crear una clase de colección personalizada. De lo contrario, solo usaría List<T> directamente.

 49
Author: Scott Wisniewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-17 17:49:58

Es recomendado que en las API públicas no se use List, sino Collection

Si usted está heredando de ella sin embargo, usted debe estar bien, afaik.

 14
Author: Darren Kopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:39:05

Prefiero usar solo List<BusinessObject>. Typedefing simplemente agrega repeticiones innecesarias al código. List<BusinessObject> es un tipo específico, no es cualquier objeto List, por lo que todavía está fuertemente escrito.

Más importante aún, declarar algo List<BusinessObject> hace que sea más fácil para todos los que leen el código decir con qué tipos están tratando, no tienen que buscar para averiguar qué es un BusinessObjectCollection y luego recordar que es solo una lista. Por typedefing, tendrás que requerir un (re)nombre consistente convención que todo el mundo tiene que seguir para que tenga sentido.

 9
Author: tghw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:34:18

Use el tipo List<BusinessObject> donde tiene que declarar una lista de ellos. Obstante, cuando devuelva una lista de BusinessObject, considere devolver IEnumerable<T>, IList<T> o ReadOnlyCollection<T> - es decir, devolver el contrato más débil posible que satisfaga al cliente.

Donde desea "agregar código personalizado" a una lista, métodos de extensión de código en el tipo de lista. Una vez más, adjunte estos métodos al contrato más débil posible, por ejemplo,

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

Por supuesto, no puede ni debe agregar estado con métodos de extensión, por lo que si necesita agregar una nueva propiedad y un campo detrás de ella, utilice una subclase o mejor, una clase wrapper para almacenar esto.

 4
Author: Anthony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-27 14:52:24

He estado yendo y viniendo en 2 opciones:

public class BusinessObjectCollection : List<BusinessObject> {}

O métodos que solo hacen lo siguiente:

public IEnumerable<BusinessObject> GetBusinessObjects();

Los beneficios del primer enfoque es que puede cambiar el almacén de datos subyacente sin tener que interferir con las firmas de los métodos. Desafortunadamente, si heredas de un tipo de colección que elimina un método de la implementación anterior, entonces tendrás que lidiar con esas situaciones a lo largo de tu código.

 4
Author: Scott Muc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-17 01:14:00

Probablemente deberías evitar crear tu propia colección para ese propósito. Es bastante común querer cambiar el tipo de estructura de datos unas cuantas veces durante las refactorizaciones o al agregar nuevas características. Con su enfoque, terminaría con una clase separada para BusinessObjectList, BusinessObjectDictionary,BusinessObjectTree, etc.

Realmente no veo ningún valor en la creación de esta clase solo porque el nombre de la clase es más legible. Sí, la sintaxis de los corchetes angulares es un poco fea., pero es estándar en C++, C# y Java, así que incluso si no escribes código que lo use, te encontrarás con él todo el tiempo.

 3
Author: Outlaw Programmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:35:09

Hago exactamente lo mismo que tú Jonathan... simplemente herede de List<T>. Obtienes lo mejor de ambos mundos. Pero generalmente solo lo hago cuando hay algún valor para agregar, como agregar un método LoadAll() o lo que sea.

 3
Author: jeremcc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:40:26

Generalmente solo derivo mis propias clases de colección si necesito "agregar valor". Como, si la colección en sí necesitaba tener algunas propiedades de" metadatos " etiquetadas junto con ella.

 2
Author: Matt Hamilton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:28:35

Puede usar ambos. Para la pereza, me refiero a la productividad, la lista es una clase muy útil, también es "completa" y francamente llena de miembros de YANGNI. Junto con el argumento sensato / recomendación presentada por el artículo de MSDN ya vinculado sobre exponer la Lista como un miembro público, prefiero la "tercera" manera:

Personalmente uso el patrón decorador para exponer solo lo que necesito de la Lista, es decir:

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();
    }    
}

Aún más probablemente abstraería OrderItemCollection en IOrderItemCollection para que pueda cambiar mi implementación de IOrderItemCollection en el futuro en (Puede que prefiera usar un objeto enumerable interno diferente como Collection o más likley para perf use una colección o Conjunto de Pares de Valores Clave.

 2
Author: Ed Blackburn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-27 14:07:59

Utilizo listas genéricas para casi todos los escenarios. La única vez que consideraría usar una colección derivada más es si agrego miembros específicos de la colección. Sin embargo, el advenimiento de LINQ ha disminuido la necesidad de incluso eso.

 1
Author: Ryan Eastabrook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 05:02:08

6 de 1, media docena de otro

De cualquier manera es lo mismo. Solo lo hago cuando tengo razones para agregar código personalizado en BusinessObjectCollection.

Sin que tenga métodos load return, una lista me permite escribir más código en una clase genérica común y hacer que funcione. Como un método de carga.

 0
Author: AdamSane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-22 03:33:17

Como alguien más señaló, se recomienda no exponer la Lista públicamente, y FxCop se quejará si lo hace. Esto incluye heredar de la Lista como en:

public MyTypeCollection : List<MyType>

En la mayoría de los casos, las API públicas expondrán IList (o ICollection oEnumerable) según corresponda.

En los casos en que desee su propia colección personalizada, puede mantener FxCop tranquilo heredando de la Colección en lugar de la Lista.

 0
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-16 18:15:57

Si elige crear su propia clase de colección, debe revisar los tipos en el sistema .Colecciones.ObjectModel Namespace .

El espacio de nombres define las clases base para facilitar a los implementadores la creación de colecciones personalizadas.

 0
Author: Hallgrim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 16:05:46

Tiendo a hacerlo con mi propia colección si quiero proteger el acceso a la lista real. Cuando usted está escribiendo objetos de negocio, la posibilidad es que usted necesita un gancho para saber si su objeto está siendo añadido / eliminado, en tal sentido creo BOCollection es mejor idea. De coz si eso no es necesario, Lista es más ligero. También es posible que desee comprobar el uso de IList para proporcionar una interfaz de abstracción adicional si necesita algún tipo de proxy (por ejemplo, una colección falsa desencadena la carga perezosa de base de datos)

Pero... ¿por qué no considerar Castle ActiveRecord o cualquier otro marco mature maduro? :)

 0
Author: William Yeung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 16:11:12

En la mayoría de las veces yo simplemente ir con la Lista, ya que me da toda la funcionalidad que necesito en el 90% del tiempo, y cuando algo 'extra' es necesario, yo herede de ella, y el código extra.

 0
Author: Adam Vigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-18 16:13:08

Yo haría esto:

using BusinessObjectCollection = List<BusinessObject>;

Esto simplemente crea un alias en lugar de un tipo completamente nuevo. Prefiero usar List directamente porque me deja libre para cambiar la estructura subyacente de la colección en algún momento en el futuro sin cambiar el código que la usa (siempre y cuando proporcione las mismas propiedades y métodos).

 0
Author: Joel Coehoorn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-10 16:07:09

Prueba esto:

System.Collections.ObjectModel.Collection<BusinessObject>

Hace innecesario implementar un método básico como CollectionBase do

 0
Author: abatishchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-27 09:45:11

Este es el camino:

Devuelve matrices, acepta IEnumerable<T>

=)

 -1
Author: Matt Hinze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-04 03:20:19