que instruccion c# iterator yield

instruccion - C#: el rendimiento dentro de un foreach falla-el cuerpo no puede ser un bloque iterador



yield return c# stack overflow (4)

Solo puede usar el yield return en una función que devuelve un IEnumerable o un IEnumerator , no un List<T> .

IEnumerable<DesktopComputer> cambiar su función para devolver un IEnumerable<DesktopComputer> .

Alternativamente, puede reescribir la función para usar List<T>.ConvertAll :

return GetComputerIdTags().ConvertAll(pcTag => new DesktopComputer() { AssetTag = pcTag, Description = "PC " + pcTag, AcquireDate = DateTime.Now });

Considera este bit de código confuso. La intención es crear un nuevo objeto sobre la marcha a través del constructor anónimo y yield return . El objetivo es evitar tener que mantener una colección local simplemente para return .

public static List<DesktopComputer> BuildComputerAssets() { List<string> idTags = GetComputerIdTags(); foreach (var pcTag in idTags) { yield return new DesktopComputer() {AssetTag= pcTag , Description = "PC " + pcTag , AcquireDate = DateTime.Now }; } }

Desafortunadamente, este bit de código produce una excepción:

Error 28 El cuerpo de ''Foo.BuildComputerAssets ()'' no puede ser un bloque de iterador porque ''System.Collections.Generic.List'' no es un tipo de interfaz de iterador

Preguntas

  • que significa este mensaje de error?
  • ¿Cómo puedo evitar este error y utilizar correctamente la yield return ?

Su firma de método es incorrecta. Debería ser:

public static IEnumerable<DesktopComputer> BuildComputerAssets()


También puede implementar la misma funcionalidad utilizando una consulta LINQ (en C # 3.0+). Esto es menos eficiente que usar el método ConvertAll , pero es más general. Más adelante, es posible que también deba usar otras funciones de LINQ, como el filtrado:

return (from pcTag in GetComputerIdTags() select new DesktopComputer() { AssetTag = pcTag, Description = "PC " + pcTag, AcquireDate = DateTime.Now }).ToList();

El método ToList convierte el resultado de IEnumerable<T> a List<T> . Personalmente no me gusta ConvertAll , porque hace lo mismo que LINQ. Pero debido a que se agregó anteriormente, no se puede usar con LINQ (se debería haber llamado Select ).


yield solo funciona en los tipos de iterador:

La declaración de rendimiento solo puede aparecer dentro de un bloque iterador

Iterators se definen como

El tipo de retorno de un iterador debe ser IEnumerable, IEnumerator, IEnumerable <T> o IEnumerator <T>.

IList e IList <T> implementan IEnumerable / IEnumerable <T>, pero cada persona que llama a un enumerador espera uno de los cuatro tipos anteriores y ninguno más.