Некоторая справочная информация;
Dictionary<string, LanguageResource> _dict_dict.Values.GetEnumerator()У меня есть LanguageResourceCollection _resources, который содержит только объекты LanguageEditorResource, и я хочу использовать LINQ для перечисления тех, которые являются грязными, поэтому я попробовал следующее. Мои конкретные вопросы выделены жирным шрифтом.
_resources.Where(r => (r as LanguageEditorResource).IsDirty)
ни где другие методы LINQ не отображаются в Intellisense, но я все равно кодирую его, и мне говорят, что «LanguageResourceCollection не содержит определения для 'Where' и никакого метода расширения ...».
Почему способ, которым LanguageResourceCollection реализует IEnumerable, не позволяет ему поддерживать LINQ?
Если я изменю запрос на (_resources as IEnumerable<LanguageEditorResource>).Where(r => r.IsDirty)
Intellisense отображает методы LINQ и компилирует решение. Но во время выполнения я получаю ArgumentNullException «Значение не может быть нулевым. Имя параметра: источник» .
Это проблема в моем коде LINQ?
Это проблема с общим дизайном классов?
Как я могу разобраться в том, что генерирует LINQ, чтобы попытаться понять, в чем проблема?
Моя цель с этим вопросом заключается не в том, чтобы получить решение конкретной проблемы, поскольку мне придется решать ее сейчас, используя другие (не LINQ) средства, а в том, чтобы попытаться улучшить свое понимание LINQ и узнать, как я могу улучшить дизайн. моих классов, чтобы лучше работать с LINQ.





Похоже, ваша коллекция реализует IEnumerable, а не IEnumerable<T>, поэтому вам нужно:
_resources.Cast<LanguageEditorResource>().Where(r => r.IsDirty)
Обратите внимание, что Enumerable.Where определен на IEnumerable<T>, а не на IEnumerable - если у вас неуниверсальный тип, вам нужно использовать Cast<T> (или OfType<T>), чтобы получить правильный тип. Разница в том, что Cast<T> выдаст исключение, если обнаружит что-то, что не является T, тогда как OfType<T> просто игнорирует все, что не является T. Поскольку вы заявили, что ваша коллекция Только содержит LanguageEditorResource, разумно проверить это предположение с помощью Cast<T>, а не отбрасывать данные молча.
Также проверьте, что у вас есть «using System.Linq» (и вы ссылаетесь на System.Core (.NET 3.5; иначе LINQBridge с .NET 2.0), чтобы получить методы расширения Where.
На самом деле, стоило бы иметь в вашей коллекции реализацию IEnumerable<LanguageResource> - что вы могли бы довольно просто сделать, используя либо метод Cast<T>, либо блок итератора (yield return).
[редактировать]
Основываясь на примечании Ричарда Пула - вы можете написать здесь свой общий контейнер своя, предположительно с T : LanguageResource (и используя этот T в Dictionary<string,T>, и реализуя IEnumerable<T> или ICollection<T>). Просто мысль.
В дополнение к ответу Марка Джи, и если вы можете это сделать, вы можете подумать об отказе от своего пользовательского класса LanguageResourceCollection в пользу общего List<LanguageResource>. Это решит вашу текущую проблему и избавится от этой неприятной пользовательской коллекции .NET 1.1.
How can I dig into what LINQ generates to try and see what the problem is?
Linq здесь ничего не генерирует. Вы можете пройти через отладчик.
to try and improve my understanding of LINQ and learn how I can improve the design of my classes to work better with LINQ.
Методы System.Linq.Enumerable в значительной степени полагаются на контракт IEnumerable <T>. Вам необходимо понять, как ваш класс может создавать цели, поддерживающие этот контракт. Тип, который представляет T, важен!
Вы можете добавить этот метод в LanguageResourceCollection:
public IEnumerable<T> ParticularResources<T>()
{
return _dict.Values.OfType<T>();
}
и назовите его:
_resources
.ParticularResources<LanguageEditorResource>()
.Where(r => r.IsDirty)
Этот пример имел бы больше смысла, если бы класс коллекции не реализовал IEnumerable <T> для того же самого _dict.Values. Дело в том, чтобы понять IEnumerable <T> и общую типизацию.
Что ж, по-прежнему необходимо перейти от LanguageResource к LanguageEditorResource и отметить внутреннее использование Dictionary <,> - это не только, базовая оболочка коллекции.