Por que você não pode usar uma palavra-chave inseguro em um contexto de iterador?
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?
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.