Qual é a melhor maneira de converter um IEnumerator para um IEnumerator genérico?
-
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
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();