У меня есть названная Группировка абстрактного класса. У меня есть подкласс под названием GroupingNNA.
public class GroupingNNA : Grouping {
// blah blah blah
}
У меня есть Список, который содержит объекты типа GroupingNNA, но, как на самом деле объявляют, содержит объекты Группировки типа.
List<Grouping> lstGroupings = new List<Grouping>();
lstGroupings.Add(
new GroupingNNA { fName = "Joe" });
lstGroupings.Add(
new GroupingNNA { fName = "Jane" });
Проблема: продолжающие LINQ запрашивают удары на мне из-за того, что lstGroupings объявляется как Список <Группировка>, и fName является свойством GroupingNNA, Не Группируясь.
var results = from g in lstGroupings
where r.fName == "Jane"
select r;
О, и это - ошибка компилятора, не ошибка периода выполнения. Заранее спасибо за любую справку на этом!
Подробнее: Вот фактический метод, который не скомпилирует. OfType () зафиксировал запрос LINQ, но компилятору не нравится то, что я пытаюсь возвратить анонимный тип как Список <Группировка>.
private List<Grouping> ApplyFilterSens(List<Grouping> lstGroupings, string fSens) {
// This works now! Thanks @Lasse
var filtered = from r in lstGroupings.OfType<GroupingNNA>()
where r.QASensitivity == fSens
select r;
if (filtered != null) {
**// Compiler doesn't like this now**
return filtered.ToList<Grouping>();
}
else
return new List<Grouping>();
}
Попробуйте:
= from g in lstGroupings.OfType<GroupingNNA>()
это пропустит любые элементы не типа GroupingNNA
, а также заставит компилятор использовать GroupingNNA
как тип для g
.
В ответ на комментарий и отредактированный вопрос. Нет, компилятор определенно не обрадуется вашей измененной коллекции, но вы можете это исправить:
return new List<Grouping>(filtered.ToArray());
Это основано на том факте, что массивы в .NET совпадают / противовариантны, что позволяет компилятору обрабатывать GroupingNNA []
как Группировка []
для конструктора.
Кроме того, вам не нужна проверка if (filter! = Null)
, вы получите коллекцию в отфильтрованной
, она может просто не создавать никаких элементов, но отфильтровано
всегда будет отличным от null
.
Это означает, что ваш код может быть записан как:
var filtered = from r in lstGroupings.OfType<GroupingNNA>()
where r.QASensitivity == fSens
select r;
return new List<Grouping>(filtered.ToArray());
или даже просто:
return new List<Grouping>((from r in lstGroupings.OfType<GroupingNNA>()
where r.QASensitivity == fSens
select r).ToArray());
или даже короче, если вы отбросите синтаксис linq:
return new List<Grouping>((lstGroupings.OfType<GroupingNNA>()
.Where(r => r.QASensitivity == fSens).ToArray());
Обратите внимание, что вы, конечно, можете использовать OfType
для пойдите и другим путем:
return filtered.OfType<Grouping>().ToList();
здесь не должно быть больших различий в производительности между разными способами, если сомневаетесь, измерьте это, но я бы выбрал то, что вы считаете наиболее легким для чтения и понимания.
Вызывая ToList
, вы снова оказываетесь в той же лодке, что и раньше - общая ковариация/контравариация не поддерживается - например, List
не совместим с List
или не конвертируем в/из List
.
Вам необходимо использовать filtered.OfType
- первый возвращает вас к IEnumerable
вместо IEnumerable
, а затем ToList
просто преобразует IEnumerable
в List
того же общего типа.