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.