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;
}
그러나 물론 컴파일러는 더미를 내뱉습니다. 왜냐하면 각각 기대한다 IEnumerable 보다는 IEnumerator.
별도의 클래스를 만들지 않고도 이 작업을 수행할 수 있는 방법이 있습니까? GetEnumerator() 방법?
해결책
컴파일러에서 알려준 대로 반환 유형을 IEnumerable로 변경해야 합니다.이것이 항복 반환 구문이 작동하는 방식입니다.
다른 팁
다시 한번 확인하기 위해
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
변경 사항
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
그게 전부입니다 :-)
IEnumerator를 반환하면 해당 메서드를 호출할 때마다 다른 열거자 개체가 됩니다(반복할 때마다 열거자를 재설정하는 것처럼 작동).IEnumerable을 반환하면 foreach는 항복 문이 있는 메서드를 기반으로 열거할 수 있습니다.
// 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
메서드는 다음 중 무엇이든 허용합니다. 씨# 또는 vb 허용 가능한 반환 유형을 고려합니다. GetEnumerator
, 다음에서 사용할 수 있는 것을 반환합니다. foreach
.매개변수가 IEnumerator<>
응답은 IEnumerable<T>
, 전화를 걸어도 GetEnumerator
일단 그것에는 나쁜 결과가 나올 가능성이 높습니다.