Список IEnumerable через цепочку переопределения

Хорошо, трудно сформулировать точный заголовок для этого вопроса, но здесь идет... У меня есть абстрактный класс Block, который выглядит примерно так:

public abstract class Block
{
   public bool Enabled{get; private set;}

   public virtual IEnumerable<KeyValuePair<string, string>> GetDefaultUsages()
   {
      yield return new KeyValuePair<string, string>("Enabled", "true");
   }
}

И скажу, что у меня есть подкласс:

public class Form : Block
{
   public string Key{get; private set;}

   public override IEnumerable<KeyValuePair<string, string>> GetDefaultUsages()
   {
       yield return new KeyValuePair<string,string>("Key", string.Empty);

       // can't do: yield return base.GetDefaultUsages()
   }
}

Идея заключается в том, что GetDefaultUsages() всегда будет возвращать IEnumerable, содержащий все строки, пары строк, которые были определены через всю цепочку наследования. Сначала я надеялся, что ключевое слово yield поддержит утверждение вроде:

yield return (some IEnumerable<T> object);

Но, видимо, это не сработает. Я понимаю, что могу сделать:

foreach(KeyValuePair<string, string> kv in base.GetDefaultUsages())
{
   yield return kv;
}

Но я надеялся на несколько более чистый синтаксис (и избегая создания ненужных промежуточных IEnumerators).

У любого есть идеи хорошего способа реализовать это.

Ответ 1

Вам нужно сделать что-то вроде метода foreach, потому что base.GetDefaultUsages() возвращает IEnumerable. yield return имеет дело с отдельными элементами, а не с коллекциями. Хотя было бы неплохо, если бы yield return мог возвращать коллекцию объекта.

2 недели назад Джон Оксли задал аналогичный вопрос.

Edit: Похоже, что Барт Джейкобс, Эрик Мейер, Фрэнк Пьенсенс и Вольфрам Шульте уже писали очень интересную статью о том, что они называют вложенными итераторами, что в основном о чем вы просите.