为什么不能在迭代器上下文中使用unsafe关键字?

时间:2010-02-11 00:28:10

标签: c# iterator unsafe

在看这个问题时,Jon在回答......'How to read a text file reversly with iterator'时做得很好。并且有一个类似的问题,我在使用指针hocus pocus ..'.net is there a way to read a text file from bottom to top'之后回答它......

现在我开始尝试使用指针尝试解决这个问题,好吧,它看起来很粗糙和边缘粗糙......

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

但发现C#编译器无法使用此实现处理此问题,但在C#编译器因错误CS1629而拒绝时遭到破坏 - “不安全的代码可能不会出现在迭代器中”

为什么会这样?

3 个答案:

答案 0 :(得分:6)

Eric Lippert在这里有一篇关于这个主题的优秀博客文章:Iterator Blocks, Part Six: Why no unsafe code?

答案 1 :(得分:6)

我想知道的是为什么你会根本使用指针。为什么不简单地说:

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

搞乱指针有什么吸引人的好处?

答案 2 :(得分:1)

这只是C#规范的一部分:

  

26.1迭代器块...迭代器块包含不安全的上下文(第27.1节)是编译时错误。一个迭代器块总是   定义一个安全的上下文,即使它的声明嵌套在一个不安全的上下文中。

据推测,编译器生成的代码需要是可验证的,以便不必标记为“不安全”。如果你想使用指针,你必须自己实现IEnumerator。