我可以有一个返回 IEnumerator<T> 的方法并在 foreach 循环中使用它吗?
-
08-06-2019 - |
题
我需要设置表单上每个文本框的高度,其中一些文本框嵌套在其他控件中。我想我可以做这样的事情:
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
if (control.Controls.Count > 0)
{
// Recursively search for any TextBoxes within each child control
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
TextBox textBox2 = control as TextBox;
if (textBox2 != null)
{
yield return textBox2;
}
}
}
像这样使用它:
foreach(TextBox textBox in FindTextBoxes(this))
{
textBox.Height = height;
}
但是编译器当然会吐出它的假值,因为 foreach 期望一个 IE可枚举 而不是一个 IE枚举器.
有没有办法做到这一点,而不必创建一个单独的类 获取枚举器() 方法?
解决方案
正如编译器告诉您的那样,您需要将返回类型更改为 IEnumerable。这就是yield return 语法的工作原理。
其他提示
只是为了澄清
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
更改为
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
这应该是全部:-)
如果返回 IEnumerator,则每次调用该方法时它将是一个不同的枚举器对象(就像在每次迭代时重置枚举器一样)。如果返回 IEnumerable,则 foreach 可以根据带有yield 语句的方法进行枚举。
// Generic function that gets all child controls of a certain type,
// returned in a List collection
private static List<T> GetChildTextBoxes<T>(Control ctrl) where T : Control{
List<T> tbs = new List<T>();
foreach (Control c in ctrl.Controls) {
// If c is of type T, add it to the collection
if (c is T) {
tbs.Add((T)c);
}
}
return tbs;
}
private static void SetChildTextBoxesHeight(Control ctrl, int height) {
foreach (TextBox t in GetChildTextBoxes<TextBox>(ctrl)) {
t.Height = height;
}
}
如果给你一个枚举器,并且需要在 for-each 循环中使用它,你可以使用以下代码来包装它:
static public class enumerationHelper { public class enumeratorHolder<T> { private T theEnumerator; public T GetEnumerator() { return theEnumerator; } public enumeratorHolder(T newEnumerator) { theEnumerator = newEnumerator;} } static enumeratorHolder<T> toEnumerable<T>(T theEnumerator) { return new enumeratorHolder<T>(theEnumerator); } private class IEnumeratorHolder<T>:IEnumerable<T> { private IEnumerator<T> theEnumerator; public IEnumerator<T> GetEnumerator() { return theEnumerator; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return theEnumerator; } public IEnumeratorHolder(IEnumerator<T> newEnumerator) { theEnumerator = newEnumerator; } } static IEnumerable<T> toEnumerable<T>(IEnumerator<T> theEnumerator) { return new IEnumeratorHolder<T>(theEnumerator); } }
这 toEnumerable
方法将接受任何 C# 或者 VB 会认为可接受的返回类型 GetEnumerator
, ,并返回可用于的东西 foreach
. 。如果参数是 IEnumerator<>
响应将是 IEnumerable<T>
, ,虽然打电话 GetEnumerator
一旦这样做可能会产生不好的结果。
不隶属于 StackOverflow