Вопрос по поводу пользовательских коллекций в C # - PullRequest
4 голосов
/ 03 августа 2009

Я хотел бы знать, какой шаблон является лучшим при возврате объектов из пользовательских классов коллекций. Чтобы проиллюстрировать мою проблему, вот пример:

У меня есть класс клиента:

public class Customer
{
   //properties
   //methods
}

Тогда у меня есть класс сбора клиентов:

public class Customercollection: Collection<Customer>
{

  public Collection<Customer> FindCustomers()
   {
     //calls DAL and gets a Collection of customers
     Collection<Customer> customers = DAL.GetCustomers();

     return customers;
   }
}

Теперь альтернативная версия этого метода может быть:

public class Customercollection: Collection<Customer>
{

  public Collection<Customer> FindCustomers()
   {
     //calls DAL and gets a Collection of customers
     Collection<Customer> customers = DAL.GetCustomers();
     foreach(Customer c in customers)
     this.Add(c);
     return this;
   }
}

Я хотел бы обсудить, какой из них лучше? И есть ли другой подход лучше, чем два выше двух?

Ответы [ 8 ]

15 голосов
/ 03 августа 2009

Я бы предложил третий подход:

Редактировать: Я обновил этот пример кода, чтобы отразить комментарии ОП ниже.

public class Customer
{
    public static ICollection<Customer> FindCustomers()
    {
        Collection<Customer> customers = new Collection<Customer>();

        foreach (CustomerDTO dto in DAL.GetCustomers())
            customers.Add(new Customer(dto));  // Do what you need to to create the customer

        return customers;
    }
}

Большую часть времени пользовательская коллекция не нужна - я предполагаю, что это один из таких случаев. Также вы можете добавить служебные методы к типу (в данном случае типу Customer), поскольку это помогает разработчику найти эти методы. (Этот вопрос больше относится к вкусу - поскольку это статический метод, вы можете поместить его в любой тип по вашему желанию, например, CustomerUtility или CustomerHelper).

Мое последнее предложение - вернуть тип интерфейса с FindCustomers(), чтобы обеспечить вам большую гибкость в будущем для изменений в реализации. Очевидно, что DAL.GetCustomers() должен будет возвращать некоторый тип, который также реализовал IList<T>, но тогда любой метод API (особенно на другом уровне, например на уровне данных) также должен возвращать типы интерфейса.

3 голосов
/ 03 августа 2009

На мой взгляд, оба они немного странные и запутанные. Когда вы расширяете класс Collection, вы подразумеваете, что ваш класс - это коллекция - так что он содержит данные. Я думаю, что когда вы сделаете этот метод статичным в первом случае, он будет иметь больше смысла:

public class Customercollection: Collection<Customer>
{

  public static Collection<Customer> FindCustomers()
   {
     //calls DAL and gets a Collection of customers
     Collection<Customer> customers = DAL.GetCustomers();

     return customers;
   }
}
2 голосов
/ 03 августа 2009

Если вы действительно хотите использовать эти методы в классе CustomerCollection, я бы предложил

public static ICollection<Customer> GetAllCustomers()

или

public void FillWithAllCustomers()

Однако я бы сказал, что ваш класс CustomerCollection является избыточным, и потребители могут напрямую обращаться к DAL, если они хотят получить коллекцию объектов клиентов.

1 голос
/ 03 августа 2009

Я бы поместил метод FindCustomers в класс DAL или создал бы класс Finder для хранения метода. Скорее всего, вам понадобятся другие методы поиска позже.

1 голос
/ 03 августа 2009

Еще один способ будет:

public class Customercollection: Collection<Customer>
{
}

public class Customer
{
    public static CustomerCollection FindCustomers()
    {
        return DAL.GetCustomers();
    }
}
0 голосов
/ 03 августа 2009

Я бы добавил этот метод расширения к предложению Эндрю:

public static Collection<T> ToCollection(this IEnumerable<T> seq) {
    return new Collection<T>(seq.ToList());
}

и используйте его так:

public static Collection<Customer> FindCustomers() { 
    return DAL.GetCustomers().Select(dto => new Customer(dto)).ToCollection();
}

Или, если вы согласитесь с советами Эндрю о возвращении типов интерфейса,

public static IList<Customer> FindCustomers() { // or ICollection
    return DAL.GetCustomers().Select(dto => new Customer(dto)).ToList();
}
0 голосов
/ 03 августа 2009

Что делать, если вы делаете что-то вроде этого:

public class CustomerCollection: Collection<Customer>
{
  public CustomerCollection: : base(new List<Customer>())
   {}

  public static IList<Customer> FindCustomers()
  {
   //return them from DAL
  }
}

Использование List в вашем конструкторе позволит вам использовать полезные методы List в вашем классе без необходимости писать собственную реализацию.

0 голосов
/ 03 августа 2009

Вы расширяете коллекцию в своем первом примере, но никогда не используете Customercollection для хранения каких-либо клиентов. Вместо этого вы возвращаете коллекцию . Мое предложение:

public static class Customers
{

  public static Collection<Customer> FindCustomers()
   {
     //calls DAL and gets a Collection of customers
     Collection<Customer> customers = DAL.GetCustomers();

     return customers;
   }
}

Используется так:

Collection<Customer> customers = Customers.FindCustomers();

Ваш второй пример также немного странный, потому что, если вы дважды вызовете FindCustomers, вы получите каждого клиента два раза в списке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...