Domanda

Sto scrivendo un ConfigurationElementCollection personalizzato per un ConfigurationHandler personalizzato in C # .NET 3.5 e desidero esporre IEnumerator come IEnumerator generico.

Quale sarebbe il modo migliore per raggiungere questo obiettivo?

Attualmente sto usando il codice:

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

Saluti

È stato utile?

Soluzione

Non credo ci sia nulla nel framework, ma potresti facilmente scriverne uno:

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

È allettante chiamare Enumerable.Cast<T> da LINQ e quindi chiamare GetEnumerator() sul risultato, ma se la tua classe implementa già IEnumerable<T> e T è un tipo di valore, che funge da no-op, quindi la StackOverflowException chiama recruit e genera un return foo.Cast<T>.GetEnumerator();. È sicuro usare foo quando <=> è sicuramente un oggetto diverso (che non è delegato a questo) ma per il resto, probabilmente è meglio usare il codice sopra.

Altri suggerimenti

IEnumerable<T> deriva già da IEnumerable quindi non è necessario eseguire alcuna conversione. Puoi semplicemente lanciarlo ... beh, in realtà non è implicito il cast necessario.

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

Fare il contrario non è molto più difficile con LINQ:

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

Stavo riscontrando lo stesso problema di overflow dello stack menzionato in alcuni dei commenti. Nel mio caso è stato dovuto al fatto che la chiamata GetEnumerator doveva essere sulla base.GetEnumerator altrimenti esegui il ciclo all'interno della tua ridefinizione di GetEnumerator.

Questo è il codice che stava lanciando lo Stack Overflow. L'uso dell'istruzione foreach chiama la stessa funzione GetEnumerator che sto cercando di sovraccaricare:

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

Ho finito con una versione semplificata del post originale in quanto non è necessario utilizzare un proprietario di elenco.

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

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

Per ottenere un IEnumerator<T> anziché un IEnumerable<T> puoi semplicemente effettuare una chiamata a GetEnumerator()

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

Questo funziona per me.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top