Есть ли хороший простой и элегантный способ сделать ICollection более свободно в C #? - PullRequest
4 голосов
/ 29 августа 2009

Пример: я хотел бы иметь Add метод ICollection пользовательского класса коллекции для реализации цепочки методов и свободно говорящих языков, чтобы я мог сделать это:

randomObject.Add("I").Add("Can").Add("Chain").Add("This").

Я могу придумать несколько вариантов, но они беспорядочные и включают в себя упаковку ICollection в другом интерфейсе и так далее.

Ответы [ 6 ]

11 голосов
/ 29 августа 2009

Хотя бегло и приятно, я бы больше интересовался добавлением AddRange (или двух):

public static void AddRange<T>(this ICollection<T> collection,
    params T[] items)
{
    if(collection == null) throw new ArgumentNullException("collection");
    if(items == null) throw new ArgumentNullException("items");
    for(int i = 0 ; i < items.Length; i++) {
        collection.Add(items[i]);
    }
}
public static void AddRange<T>(this ICollection<T> collection,
    IEnumerable<T> items)
{
    if (collection == null) throw new ArgumentNullException("collection");
    if (items == null) throw new ArgumentNullException("items");
    foreach(T item in items) {
        collection.Add(item);
    }
}

Подход params T[] позволяет AddRange(1,2,3,4,5) и т. Д., А IEnumerable<T> позволяет использовать такие вещи, как запросы LINQ.

Если вы хотите использовать свободный API, вы также можете написать Append в качестве метода расширения в C # 3.0, который сохраняет исходный тип списка , путем соответствующего использования общих ограничений:

    public static TList Append<TList, TValue>(
        this TList list, TValue item) where TList : ICollection<TValue>
    {
        if(list == null) throw new ArgumentNullException("list");
        list.Add(item);
        return list;
    }
    ...
    List<int> list = new List<int>().Append(1).Append(2).Append(3);

(обратите внимание, что возвращается List<int>)

5 голосов
/ 29 августа 2009

Вы также можете использовать метод расширения, который можно использовать с любым ICollection<T> и избавить вас от написания собственного класса коллекции:

public static ICollection<T> ChainAdd<T>(this ICollection<T> collection, T item)
{
  collection.Add(item);
  return collection;
}
3 голосов
/ 29 августа 2009

Вам нужно будет вернуть void из Add, как это указано в ICollection. Я полагаю, что это исключает использование метода Add с использованием только одного параметра.

Не совсем то, что вы хотите, но вы можете добавить что-то вроде этого в свой тип коллекции.

public CustomCollectionType Append(string toAdd)
{
  this.Add(string toAdd);
  return this;
}

Тогда вы можете сделать:

customCollection.Append("This").Append("Does").Append("Chain");

Надеюсь, это поможет,

Dan

2 голосов
/ 29 августа 2009

Другой вариант - использовать инициализатор коллекции C #:

var list = new YourList<String>()
    {
         "Hello",
         "World",
         "etc..."
    };
0 голосов
/ 29 августа 2009

Без обид, но, возможно, вы бы предпочли VB.NET

Это более благоприятно для программирования на «естественном языке», чем на C #.

В VB.NET у вас есть конструкция «с», которая позволит вам:

With myCollection
    .Add("Hello")
    .Add("There")
    .Add("My")
    .Add("Name")
    .Add("Is")
    .Add("Silky")
    .Sort()
End With
0 голосов
/ 29 августа 2009

Вы можете скрыть метод ICollection.Add в своем пользовательском классе коллекции и вернуть его.

public class MyList<T>:List<T>
{
  public new MyList<T> Add(T item)
  {
     (this as ICollection<T>).Add(item);
     return this;
  }
}

тогда вы можете добавить пункт с цепочкой Добавить звонки:

MyList<string> strList = new MyList<string>();
strList.Add("Hello").Add(" ").Add("World!");
...