9

In looking at this question which Jon did a fine job in answering... 'How to read a text file reversly with iterator'. And there was a similar question in which I answered using pointers hocus pocus..'.net is there a way to read a text file from bottom to top' before it got closed....

Now I did set out to try solve this using pointers, ok, it looks hackish and rough around the edges...

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

but discovered that C# compiler cannot handle this using this implementation but was devastated when the C# compiler refused with an error CS1629 - 'Unsafe code may not appear in iterators'

Why is that so?

Community
  • 1
  • 1
t0mm13b
  • 34,087
  • 8
  • 78
  • 110

3 Answers3

10

Eric Lippert has an excellent blog post on this topic here: Iterator Blocks, Part Six: Why no unsafe code?

svick
  • 236,525
  • 50
  • 385
  • 514
Kevin Pullin
  • 13,122
  • 3
  • 24
  • 33
8

What I want to know is why you would use pointers for this at all. Why not simply say:

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

What's the compelling benefit of messing around with pointers?

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
1

It's just part of the C# spec:

26.1 Iterator blocks ... It is a compile-time error for an iterator block to contain an unsafe context (§27.1). An iterator block always defines a safe context, even when its declaration is nested in an unsafe context.

Presumably, the code that gets generated by the compiler needs to be verifiable in order to not have to be labelled 'unsafe'. If you want to use pointers, you'll have to implement IEnumerator yourself.

codekaizen
  • 26,990
  • 7
  • 84
  • 140
  • Thanks for your answer, but surely the usage of the fixed keyword is guaranteed that you are within the boundaries...??? like you're hardly going to trample something that is not belonging to your code...and it's readonly, so ... – t0mm13b Feb 11 '10 at 00:34
  • @tommieb75: Not true, there are unverifiable side effects using pointers. Oh, Eric Lippert discusses this... off to read! – codekaizen Feb 11 '10 at 00:37
  • Eric's entire series on iterator blocks is a great resource! Scratch that - his entire blog is **awesome**. – Kevin Pullin Feb 11 '10 at 01:10