Я заметил, что все методы расширения Linq Where
, Any
, Take
и т. Д. Все возвращают IEnumerable
.Для моего приложения было бы намного лучше, если бы они возвращали экземпляр того же типа, что и тот, к которому я обращаюсь.
Так, например, если я вызову myList.Where(...)
на LinkedList
, я быхотел бы получить LinkedList
назад, на List
я хотел бы List
назад и т. д.
Это становится более раздражающим, когда у меня есть такой тип как
class MyType
{
public string MyField;
}
class MyCollection : List<MyType>
{
// Some useful stuff in here
}
в этом случае я хотел бы иметь возможность сделать
MyCollection source = .......
MyCollection filtered = source.Where(obj => obj.MyField != null);
К сожалению, это не будет работать из коробки.Тем не менее, я подошел ближе, используя следующий код
public static ListType Filtered<ListType, ElementType>(this ListType @this, Predicate<ElementType> filter) where ListType : class, ICollection<ElementType>, new()
{
// Arguments checks omitted
// Create return instance
var filtered = new ListType();
// Apply filter for each element
foreach (var item in @this)
{
if (filter(item))
filtered.Add(item);
}
return filtered;
}
, который я могу сделать (обратите внимание на строго типизированный делегат)
MyCollection source = .......
MyCollection filtered = source.Filtered((MyType obj) => obj.MyField != null);
Поэтому мой вопрос: зачем мне второйуниверсальный аргумент в Filter<ListType, ElementType>
, когда я указываю where ListType : ICollection<ElementType>
?Я понимаю, что не могу использовать в where
универсальные типы, которые я не добавил в объявление метода, но почему это так?Есть ли лучший способ сделать это, что я упустил из виду?