2009-05-06 10 views
28

Ich schreibe eine benutzerdefinierte ConfigurationElementCollection für einen benutzerdefinierten ConfigurationHandler in C# .NET 3.5 und ich möchte den IEnumerator als generische IEnumerator verfügbar machen.Was ist der beste Weg, um einen IEnumerator in einen generischen IEnumerator zu konvertieren?

Was wäre der beste Weg, dies zu erreichen?

Ich bin derzeit mit dem Code:

 
public new IEnumerator<GenericObject> GetEnumerator() 
{ 
    var list = new List(); 
    var baseEnum = base.GetEnumerator(); 
    while(baseEnum.MoveNext()) 
    { 
    var obj = baseEnum.Current as GenericObject; 
    if (obj != null) 
     list.Add(obj); 
    } 
    return list.GetEnumerator(); 
} 

Prost

Antwort

45

Ich glaube nicht, dass es im Rahmen alles ist, aber man konnte leicht schreiben ein:

IEnumerator<T> Cast<T>(IEnumerator iterator) 
{ 
    while (iterator.MoveNext()) 
    { 
     yield return (T) iterator.Current; 
    } 
} 

Es ist verlockend, rufen Sie einfach Enumerable.Cast<T> von LINQ und rufen Sie dann GetEnumerator() auf das Ergebnis - aber wenn Ihre Klasse implementiert bereits IEnumerable<T> und T ist ein Werttyp, der als No-Op fungiert, so dass der Aufruf GetEnumerator() recursiert und einen StackOverflowException auslöst. Es ist sicher zu verwenden return foo.Cast<T>.GetEnumerator();, wenn foo ist definitiv ein anderes Objekt (das nicht zurück zu diesem delegieren), aber ansonsten sind Sie wahrscheinlich am besten mit dem Code oben.

+7

Kannst du den Enumerator nicht einfach von der Besetzung zurückgeben? Rückgabe this.Cast (). GetEnumerator(); – flq

+0

Frank: Du hast absolut Recht :) –

+0

Das ist es danke. Vielen Dank für Ihre Antworten. – zonkflut

3

IEnumerable<T> bereits von IEnumerable leitet, so gibt es keine Notwendigkeit, eine Umwandlung zu tun. Sie können einfach auf ihn werfen ... Nun, eigentlich ist es implizit keine Besetzung notwendig.

IEnumerable<T> enumerable = GetGenericFromSomewhere(); 
IEnumerable sadOldEnumerable = enumerable; 
return sadOldEnumerable.GetEnumerator(); 

andersrum gehen ist nicht viel schwieriger, mit LINQ:

var fancyEnumerable = list.OfType<GenericObject>(); 
return fancyEnumerable.GetEnumerator(); 
+0

Meine schlechte verpasst den generischen Teil meiner Methodendefinition – zonkflut

+2

Sie verwirren IEnumerable und IEnumerator. IEnumerable leitet sich von IEnumerable ab und IEnumerator leitet sich von IEnumerator ab.Es macht nicht viel Sinn, "IEnumerable theEnumerator" zu sagen, weil ein Enumerable kein Enumerator ist. –

+0

Casting funktioniert nicht, da die Auflistung im übergeordneten Objekt in einer ArrayList gespeichert ist. – zonkflut

0

Sie können OfType<T> und Cast<T> verwenden.

public static IEnumerable Digits() 
{ 
    return new[]{1, 15, 68, 1235, 12390, 1239}; 
} 

var enumerable = Digits().OfType<int>(); 
foreach (var item in enumerable) 
    // var is here an int. Without the OfType<int(), it would be an object 
    Console.WriteLine(i); 

Um ein IEnumerator<T> anstelle eines IEnumerable<T> bekommen Sie können nur einen Anruf zu GetEnumerator()

var enumerator = Digits().OfType<int>().GetEnumerator(); 
0

für mich Dies funktioniert machen.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator(); 
0

Ich wurde in der gleichen Stack-Überlauf Problem erwähnt ausgeführt ist, einige der Kommentare. In meinem Fall war es aufgrund der Tatsache, dass der GetEnumerator-Aufruf auf dem base.GetEnumerator erfolgen musste, sonst würden Sie innerhalb Ihrer eigenen GetEnumerator-Neudefinition eine Schleife bilden.

Dies ist der Code, der den Stack Overflow geworfen hat. Die Verwendung der foreach-Anweisung rufen Sie die gleiche Funktion GetEnumerator ich Überlastung bin versucht:

public new IEnumerator<T> GetEnumerator() 
{ 
    foreach (T type in this) 
    { 
     yield return type; 
    } 
} 

Ich habe mit einer vereinfachten Version des Original-Post endete als Sie keine Liste Halter verwenden müssen.

Verwandte Themen