2009-05-06 13 views
28

Estoy escribiendo una ConfigurationElementCollection personalizada para un ConfigurationHandler personalizado en C# .NET 3.5 y quiero exponer el IEnumerator como un IEnumerator genérico.¿Cuál es la mejor manera de convertir un IEnumerator a un IEnumerator genérico?

¿Cuál sería la mejor manera de lograrlo?

actualmente estoy usando el código:

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

Saludos

Respuesta

45

No creo que haya nada en el marco, pero fácilmente podría escribir uno:

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

Es tentador simplemente llamar a Enumerable.Cast<T> desde LINQ y luego llamar al GetEnumerator() en el resultado, pero si su clase ya implementa IEnumerable<T> y T es un tipo de valor, que actúa como no operativa, por lo que la llamada GetEnumerator() se repite y arroja un StackOverflowException. Es seguro usar return foo.Cast<T>.GetEnumerator(); cuando foo es definitivamente un objeto diferente (que no vuelve a delegar en este) pero, de lo contrario, probablemente sea mejor que use el código anterior.

+7

¿No puedes devolver el Enumerator del elenco? return this.Cast () .GetEnumerator(); – flq

+0

Frank: Tienes toda la razón :) –

+0

Eso es gracias. Gracias a todos por sus respuestas. – zonkflut

3

IEnumerable<T> ya se deriva de IEnumerable lo que no hay necesidad de hacer ningún tipo de conversión. Simplemente puedes lanzarlo ... bueno, en realidad está implícito que no es necesario un lanzamiento.

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

ir al revés no es mucho más difícil con LINQ:

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

Mi mal pasó por alto la parte genérica de la definición de mi método – zonkflut

+2

Estás confundiendo IEnumerable e IEnumerator. IEnumerable proviene de IEnumerable e IEnumerator proviene de IEnumerator.No tiene mucho sentido decir "IEnumerable theEnumerator" porque un enumerable no es un enumerador. –

+0

fundición no funciona como en el objeto principal de la colección se almacena en una ArrayList. – zonkflut

0

Puede usar OfType<T> y Cast<T>.

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

Para tener una IEnumerator<T> en lugar de un IEnumerable<T> puede simplemente hacer una llamada a GetEnumerator()

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

Esto funciona para mí.

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

Me encontré con el mismo problema de desbordamiento de la pila mencionado es algunos de los comentarios. En mi caso, se debió al hecho de que la llamada a GetEnumerator tenía que estar en la base.GetEnumerator, de lo contrario, realiza un bucle dentro de su propia redefinición de GetEnumerator.

Este es el código que arrojaba el desbordamiento de la pila. El uso de la instrucción foreach llamar la misma función GetEnumerator Estoy tratando de sobrecarga:

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

he terminado con una versión simplificada del post original, ya que no es necesario utilizar un soporte de lista.

public class ElementCollection<T> : ConfigurationElementCollection, IList<T> 
    ... 
    public new IEnumerator<T> GetEnumerator() 
    { 
     var baseEnum = base.GetEnumerator(); 
     while (baseEnum.MoveNext()) 
     { 
      yield return baseEnum.Current as T; 
     } 
    } 
    ... 
} 
Cuestiones relacionadas