Извлечение исходного типа из IEnumerator - PullRequest
0 голосов
/ 06 июля 2018

Пример - я могу написать метод, который возвращает доход по каждому элементу в списке, например:

IEnumerator test1()
{
    List<int> list = new List<int> { 0, 1, 2, 3, 4 };

    foreach (int entry in list)
    {
        yield return entry;
    }
}

Возвращает результаты в IEnumerator, который хранит каждый результат как объект. Я все еще могу вернуть целые числа с преобразованием, хотя, как это:

IEnumerator testEnumerator = test1();

while (testEnumerator.MoveNext())
{
    int i = Convert.ToInt32(testEnumerator.Current);
    Console.WriteLine(i);
}

Однако, что если значения, которые я возвращаю с помощью yield return, относятся к типу, в который я не могу легко преобразовать?

IEnumerator test2()
{
    System.Windows.Controls.CheckBox checkbox1 = new System.Windows.Controls.CheckBox();
    System.Windows.Controls.CheckBox checkbox2 = new System.Windows.Controls.CheckBox();
    System.Windows.Controls.CheckBox checkbox3 = new System.Windows.Controls.CheckBox();
    List<System.Windows.Controls.CheckBox> list = new List<System.Windows.Controls.CheckBox> { checkbox1, checkbox2, checkbox3 };

    foreach (FrameworkElement entry in list)
    {
        yield return entry;
    }
}

Кроме того, что если test2 () не обязательно знает тип, который он будет возвращать? В идеале это была бы функция для рекурсивного поиска визуального дерева элементов пользовательского интерфейса и возврата всех дочерних элементов типа [blank]. Однако человек, вызывающий test2 (), будет знать, к какому типу он должен возвращаться.

Как я могу получить экземпляр FrameworkElement или Checkbox обратно из универсального IEnumerator.Current?

Я должен отметить, что хотя я знаю, какой тип мне следует возвращать из test2 () в вызывающем его методе, test2 () не всегда возвращает этот тип. Он может вернуть любой тип FrameworkElement, включая TextBox, Grid, Border и т. Д. Я бы предпочел сделать это без изменения того, что возвращает test2 (), или хотя бы оставить его универсальным.

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Я понял это (частично основываясь на некоторых подсказках, которые я видел в этих комментариях и ответах).

Во-первых, сделайте так, чтобы test2 () возвращал IEnumerator из FrameworkElements вместо общего:

    IEnumerator<FrameworkElement> test2()
    {
        System.Windows.Controls.CheckBox checkbox1 = new System.Windows.Controls.CheckBox();
        System.Windows.Controls.CheckBox checkbox2 = new System.Windows.Controls.CheckBox();
        System.Windows.Controls.CheckBox checkbox3 = new System.Windows.Controls.CheckBox();
        List<System.Windows.Controls.CheckBox> list = new List<System.Windows.Controls.CheckBox> { checkbox1, checkbox2, checkbox3 };

        foreach (FrameworkElement entry in list)
        {
            yield return entry;
        }
    }

Во-вторых, я могу использовать это преобразование для переключения с FrameworkElement на более конкретный тип после получения результатов:

        IEnumerator<FrameworkElement> testEnumerator2 = test2();

        while (testEnumerator2.MoveNext())
        {
            System.Windows.Controls.CheckBox checkbox = (System.Windows.Controls.CheckBox)testEnumerator2.Current;
            Console.WriteLine(checkbox.IsChecked);
        }
0 голосов
/ 06 июля 2018

Ваш первый выбор - использовать универсальную версию IEnumerator<CheckBox>

public static IEnumerator<CheckBox> test1()
{
   CheckBox checkbox1 = new CheckBox();
   CheckBox checkbox2 = new CheckBox();
   CheckBox checkbox3 = new CheckBox();
   List<CheckBox> list = new List<CheckBox> { checkbox1, checkbox2, checkbox3 };

   foreach (var entry in list)
   {
      yield return entry;
   }
}

Однако вы также можете легко использовать IEnumerable<CheckBox>, у него также есть свои преимущества (в зависимости от ваших потребностей)

public static IEnumerable<CheckBox> test2()
{
   CheckBox checkbox1 = new CheckBox();
   CheckBox checkbox2 = new CheckBox();
   CheckBox checkbox3 = new CheckBox();
   List<CheckBox> list = new List<CheckBox> { checkbox1, checkbox2, checkbox3 };

   foreach (var entry in list)
   {
      yield return entry;
   }
}

Обычаи

var testEnumerator = test1();

while (testEnumerator.MoveNext())
{
   // i am a CheckBox
   CheckBox checkBox = testEnumerator.Current;

}

foreach (var item in test2())
{
   // i am a CheckBox also
   CheckBox checkBox = item;
}

Дополнительные ресурсы

IEnumerable Interface

Предоставляет перечислитель, который поддерживает простую итерацию по коллекция указанного типа.

Интерфейс IEnumerator

Поддерживает простую итерацию по общей коллекции.

...