2009-07-01 9 views

Respuesta

36

yield return obras para exactamente 4 casos:

  • IEnumerable
  • IEnumerable<T>
  • IEnumerator
  • IEnumerator<T>

Esto se debe a que tiene que construir una máquina de estados internos; un diccionario (etc.) no sería posible con esto. Por supuesto, puede simplemente return un tipo adecuado.

+0

Artículo útil aquí http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx si desea implementar IEnumerable usted mismo. – Rory

+0

@Rory sí, implementarlo usted mismo es un PITA masivo, y no puedo pensar en ninguna razón "normal" para hacerlo, ahora que existen bloques iteradores. Tengo algunos de estos, pero eso suele ser compatible con los proyectos que deben compilarse incluso en los compiladores de C# 1.2; no exactamente el escenario "normal". –

+0

De acuerdo, aunque IGrouping podría ser bueno en algunos casos, parece más fácil usar un IEnumerable > en su lugar para que obtenga la magia del retorno de rendimiento. – Rory

0

No, sólo :-) IEnumerable

+0

No es cierto; ver mi respuesta ;-p –

1

Yo no lo creo. Si bien el documentation no lo especifica exactamente, la forma en que está redactado implica que solo se puede usar cuando el tipo de devolución del método sea IEnumerable o IEnumerable<T>. Es posible que pueda escribir una clase que implemente IGrouping dando un IEnumerable (que sería devuelto por su método usando yield return), pero esa es la única opción realmente.

+1

La especificación del idioma lo explica en su lugar ... ver 8.18 en ECMA 334 –

2

No, porque un bloque de iterador es simplemente una máquina de estados construida en su nombre por el compilador. Esta característica le permite "ceder" y el elemento como una parte de una secuencia.

Si el tipo de devolución no era IEnumerable<T> (como IDictionary por ejemplo) el compilador tendría que generar métodos para implementar esa interfaz y en ese punto no tendría mucho sentido porque estaría trabajando con una colección en lugar de una secuencia.

15

Sin embargo, podría devolver IEnumerable<KeyValuePair<K,V>> que sería similar a un diccionario. A continuación, obtendrías return KeyValuePairs. Incluso podría envolver esto con otro método que crea un diccionario a partir de la devolución. Lo único que el primer método no garantizaría es la singularidad en las claves.

+7

Luego pierde el tiempo de acceso O (1), y tiene que pasar por cada KVP para encontrar la clave correcta, tomando al peores O (n) veces. –

4

Respuesta: No. Una declaración yield return se puede utilizar sólo si el tipo de retorno es IEnumerator, IEnumerator<T>, IEnumerable, o IEnumerable<T>.

De §8.14 de la C# 3.0 spec:

La declaración de rendimiento se utiliza en un bloque de iterador (§8.2) para producir un valor para el objeto empadronador (§10.14.4) o un objeto enumerable (§10.14.5) de un iterador o para señalar el final de la iteración.

De §10.14.4:

objeto Un enumerador tiene las siguientes características:

  1. Implementa IEnumerator y IEnumerator<T>, en donde T es el tipo de rendimiento del iterador.

[...]

De §10.14.5:

Un objeto enumerable tiene las siguientes características:

  1. Implementa IEnumerable y IEnumerable<T>, donde T es el tipo de rendimiento del iterador.

[...]

2

Sólo tiene que llamar al método iterador y la cadena ToDictionaryGroupBy o después de ella, y tiene la misma cosa. Ponlo en un método de envoltura de una línea si necesitas llamarlo así desde varios lugares.

-2

Como el yield return se puede utilizar con tipos como IEnumerator<T> ¿por qué no hacer algo como esto?

internal static IEnumerable<Dictionary<byte, string>> GetData() 
    { 
     Dictionary<byte, string> result = GetMyData(); //read from db 
     yield return result; 
    } 

Espero que ayude.

+0

Usted está 'produciendo una lista de diccionarios enteros, no pares clave-valor. – titol

Cuestiones relacionadas