从 IEnumerator 检索原始类型

Retrieving the original type from an IEnumerator

示例 - 我可以编写一个方法对列表中的每个项目执行 yield return,如下所示:

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

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

它return将结果保存在一个 IEnumerator 中,它将每个结果作为一个对象保存。不过,我仍然可以通过转换取回整数,如下所示:

IEnumerator testEnumerator = test1();

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

但是,如果我 return 使用 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() 不一定知道它将 returning 的类型怎么办?理想情况下,这将是一个递归搜索 UI 元素和 return 所有类型 [blank] 子元素的可视化树的函数。然而,调用 test2() 的人将知道他们应该返回什么类型。

如何从通用 IEnumerator.Current 中取回 FrameworkElement 或 Checkbox 的实例?

我应该注意,虽然我知道我应该在调用它的方法中从 test2() 返回什么类型,但 test2() 不一定总是 return类型。它可以 return 任何类型的 FrameworkElement,包括 TextBox、Grid、Border 等。我最好不要修改 test2() return 或至少保持它的通用性。

您的首选是使用通用版本 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

Exposes the enumerator, which supports a simple iteration over a collection of a specified type.

IEnumerator Interface

Supports a simple iteration over a generic collection.

我想通了(部分基于我在这些评论和答案中看到的一些线索)。

首先,使用 test2() return FrameworkElements 的 IEnumerator 而不是通用的:

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