2010-02-11 10 views
5

Al ver esta pregunta, Jon hizo un buen trabajo al responder ... 'How to read a text file reversly with iterator'. Y hubo una pregunta similar en la que respondí usando punteros hocus pocus ... '.net is there a way to read a text file from bottom to top' antes de que se cerrara ...¿Por qué no puede usar una palabra clave insegura en un contexto de iterador?

Ahora me propuse intentar solucionar esto usando punteros, está bien, parece áspero y áspero alrededor de los bordes ...

 
public class ReadChar : IEnumerable<char> 
{ 
    private Stream _strm = null; 
    private string _str = string.Empty; 
    public ReadChar(string s) 
    { 
     this._str = s; 
    } 
    public ReadChar(Stream strm) 
    { 
     this._strm = strm; 
    } 
    public IEnumerator<char> GetEnumerator() 
    { 
     if (this._strm != null && this._strm.CanRead && this._strm.CanSeek) 
     { 
      return ReverseReadStream(); 
     } 
     if (this._str.Length > 0) 
     { 
      return ReverseRead(); 
     } 
     return null; 
    } 

    private IEnumerator<char> ReverseReadStream() 
    { 
     long lIndex = this._strm.Length; 
     while (lIndex != 0 && this._strm.Position != 0) 
     { 
      this._strm.Seek(lIndex--, SeekOrigin.End); 
      int nByte = this._strm.ReadByte(); 
      yield return (char)nByte; 
     } 
    } 

    private IEnumerator<char> ReverseRead() 
    { 
     unsafe 
     { 
      fixed (char* beg = this._str) 
      { 
       char* p = beg + this._str.Length; 
       while (p-- != beg) 
       { 
        yield return *p; 
       } 
      } 
     } 
    } 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

pero descubrieron que compilador de C# no puede manejar esta usando esta aplicación, pero fue devastado cuando el compilador de C# se negó con un CS1629 de error - 'código no seguro puede no aparecer en los iteradores'

¿Por qué es así?

+0

Piensa en cómo 'yield return' funciona bajo el capó. –

Respuesta

1

Es sólo una parte de la especificación C#:

26.1 bloques Iterator ... Es un error en tiempo de compilación para un bloque de iterador que contiene un contexto inseguro (§27.1). Un bloque iterador siempre define un contexto seguro, incluso cuando su declaración está anidada en un contexto inseguro.

Presumiblemente, el código que genera el compilador necesita ser verificable para no tener que etiquetarse como "inseguro". Si desea utilizar punteros, deberá implementar IEnumerator usted mismo.

+0

Gracias por su respuesta, pero seguramente el uso de la palabra clave fija está garantizado de que usted está dentro de los límites ... ??? como si no fuera a pisotear algo que no pertenece a su código ... y es de solo lectura, por lo que ... – t0mm13b

+0

@ tommieb75: No es cierto, hay efectos secundarios no verificables usando punteros. ¡Oh, Eric Lippert discute esto ... fuera para leer! – codekaizen

+0

Gracias! ;) Estoy leyéndolo también y estoy reflexionando al respecto ... – t0mm13b

6

Lo que quiero saber es por qué se usaría punteros para esto en absoluto. ¿Por qué no simplemente decir:

private IEnumerator<char> ReverseRead() 
{ 
    int len = _str.Length; 
    for(int i = 0; i < len; ++i) 
     yield return _str[len - i - 1]; 
} 

¿Cuál es la ventaja de meterse con los punteros?

Cuestiones relacionadas