Проблема с наследованием и списком <> - PullRequest
7 голосов
/ 14 мая 2010

У меня есть абстрактный класс под названием Группировка. У меня есть подкласс под названием GroupingNNA.

public class GroupingNNA : Grouping {
  // blah blah blah
}

У меня есть список, который содержит элементы типа GroupingNNA, но фактически объявлен как содержащий элементы типа Grouping.

List<Grouping> lstGroupings = new List<Grouping>();
lstGroupings.Add(
  new GroupingNNA { fName = "Joe" });
lstGroupings.Add(
  new GroupingNNA { fName = "Jane" });

Проблема: Следующий запрос LINQ подрывает меня из-за того, что lstGroupings объявлен как List , а fName является свойством GroupingNNA, а не Grouping.

var results = from g in lstGroupings
              where r.fName == "Jane"
              select r;

О, и это ошибка компилятора, а не ошибка времени выполнения. Заранее спасибо за любую помощь в этом!

Подробнее: Вот фактический метод, который не будет компилироваться. OfType () исправил запрос LINQ, но компилятору не нравится тот факт, что я пытаюсь вернуть анонимный тип в виде List .

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>();
  }

Ответы [ 2 ]

6 голосов
/ 14 мая 2010

Попробуйте:

= from g in lstGroupings.OfType<GroupingNNA>()

это пропустит любые элементы не типа GroupingNNA, а также заставит компилятор использовать GroupingNNA в качестве типа для g.

В ответ на комментарий и отредактированный вопрос. Нет, компилятор определенно не будет рад вашей измененной коллекции, но вы можете это исправить:

return new List<Grouping>(filtered.ToArray());

Это зависит от того факта, что массивы в .NET являются ко / противоположными вариантами, что позволяет компилятору обрабатывать GroupingNNA[] как Grouping[] для конструктора.

Кроме того, вам не нужна проверка if (filtered != null), вы получите коллекцию в filtered, она может просто не создавать никаких элементов, но filtered всегда будет не 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();

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

5 голосов
/ 14 мая 2010

При вызове ToList<AnotherType>() вы возвращаетесь в ту же лодку, что и раньше, - общая ковариация / контрвариантность не поддерживается - например, List<Type> не совместимо с или не конвертируется в / из List<SubType>.

Вам нужно использовать filtered.OfType<Grouping>().ToList(); - сначала вы вернетесь к IEnumerable<Grouping> вместо IEnumerable<GroupingNNA>, а затем ToList просто преобразует IEnumerable в List того же универсального типа.

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