Qual é a melhor maneira de converter um IEnumerator para um IEnumerator genérico?

StackOverflow https://stackoverflow.com/questions/828342

  •  06-07-2019
  •  | 
  •  

Pergunta

Eu estou escrevendo um ConfigurationElementCollection personalizado para um ConfigurationHandler personalizado em C # .NET 3.5 e estou querendo expor o IEnumerator como um IEnumerator genérico.

Qual seria a melhor maneira de conseguir isso?

Atualmente, estou usando o 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();
}

Felicidades

Foi útil?

Solução

Eu não acredito que haja algo no quadro, mas você poderia facilmente escrever um:

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

É tentador Enumerable.Cast<T> apenas chamada de LINQ e GetEnumerator() então chamada no resultado - mas se sua classe já implementa IEnumerable<T> e T é um tipo de valor, que atua como um não-op, por isso os recurses chamada GetEnumerator() e lança um StackOverflowException . É seguro usar return foo.Cast<T>.GetEnumerator(); quando foo é definitivamente um diferente objeto (o que não delegar volta a este), mas caso contrário, você está provavelmente melhor fora de usar o código acima.

Outras dicas

IEnumerable<T> já deriva IEnumerable por isso não há necessidade de fazer qualquer conversão. Você pode simplesmente lançar a ele ... bem, na verdade, não é nenhuma implícita lançar necessário.

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

Indo o contrário não é muito mais difícil com LINQ:

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

Eu estava correndo para o mesmo problema de estouro de pilha mencionado é alguns dos comentários. No meu caso, foi devido ao fato de que a chamada GetEnumerator precisava estar ao base.GetEnumerator caso contrário você laço dentro de sua própria redefinição GetEnumerator.

Este é o código que foi Jogando o estouro de pilha. O uso da instrução foreach chamar a mesma função GetEnumerator Estou tentando sobrecarga:

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

Eu acabei com uma versão simplificada do post original que você não precisa usar um porta-List.

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;
        }
    }
    ...
}

Você pode usar OfType<T> e 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 se ter uma IEnumerator<T> em vez de um IEnumerable<T> você pode apenas fazer uma chamada para GetEnumerator()

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

Isso funciona para mim.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top