Por que você não pode usar uma palavra-chave inseguro em um contexto de iterador?

StackOverflow https://stackoverflow.com/questions/2241417

  •  19-09-2019
  •  | 
  •  

Pergunta

Ao olhar para esta questão que Jon fez um bom trabalho em responder ... ' Como ler um arquivo de texto reversly com iterator '. E havia uma pergunta semelhante em que eu respondi usando ponteiros Hocus Pocus .. '. net há uma maneira de ler um arquivo de texto de baixo para cima ' antes que ficasse fechada ....

Agora eu tinha estabelecidos para tentar resolver isso usando ponteiros, ok, parece hackish e áspero em torno das bordas ...

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

mas descobriu que compilador C # não pode lidar com isso usando essa implementação, mas foi devastada quando o compilador C # recusou com uma CS1629 de erro - 'código inseguro pode não aparecer no iterators'

Por que é assim?

Foi útil?

Solução

Eric Lippert tem um excelente post sobre este tema aqui: Iterator Blocks, Parte VI:? Por que nenhum código inseguro

Outras dicas

O que eu quero saber é por que você iria usar ponteiros para tudo isso. Por que não dizer simplesmente:

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

Qual é a vantagem convincente de andar com ponteiros?

É apenas parte do C # spec:

26.1 blocos Iterator ... É um erro em tempo de compilação para um bloco iterador para conter um contexto inseguro (§27.1). Um bloco de iterator sempre define um contexto seguro, mesmo quando a sua declaração está aninhado em um contexto inseguro.

Presumivelmente, o código que é gerado pelo compilador tem de ser verificável, a fim de não ter de ser rotulado 'inseguro'. Se você quiser usar ponteiros, você vai ter que implementar IEnumerator si mesmo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top