Pregunta

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

Salud

¿Fue útil?

Solución

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

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

Es tentador simplemente llamar Enumerable.Cast<T> desde LINQ y luego llamar GetEnumerator() en el resultado - pero si su clase ya implementa IEnumerable<T> y T es un tipo de valor que actúa como no operativo, por lo que el GetEnumerator() llama recursivamente y lanza un StackOverflowException.Es seguro de usar return foo.Cast<T>.GetEnumerator(); cuando foo es definitivamente un diferente object (que no delega a este) pero, de lo contrario, probablemente sea mejor que utilices el código anterior.

Otros consejos

IEnumerable<T> ya se deriva de IEnumerable, por lo que no es necesario realizar ninguna conversión. Simplemente puede lanzarlo ... bueno, en realidad es implícito, no es necesario lanzarlo.

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

Me encontraba con el mismo problema de desbordamiento de pila mencionado en algunos de los comentarios. En mi caso, se debió al hecho de que la llamada GetEnumerator tenía que ser a la base. GetEnumerator, de lo contrario, se repite dentro de su propia redefinición GetEnumerator.

Este es el código que arrojó el desbordamiento de pila. El uso de la instrucción foreach llama a la misma función GetEnumerator que intento sobrecargar:

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

Terminé con una versión simplificada de la publicación original, ya que no es necesario utilizar un titular de la 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;
        }
    }
    ...
}

Puedes 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 conseguir un IEnumerator<T> en lugar de un IEnumerable<T> puedes simplemente hacer una llamada a GetEnumerator()

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

Esto funciona para mí.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top