1

What is the precise implementation of Enumerable.Range in .Net; preferable .Net 4? Is it a yielded for-loop? A custom implementation (IEnumerable, IEnumerator) or?

Bent Rasmussen
  • 5,538
  • 9
  • 44
  • 63
  • 2
    decompile it with reflector http://www.red-gate.com/products/reflector/ – Mauricio Scheffer Oct 05 '09 at 13:45
  • The reason I care about this is because I want to know how efficient the implementation is and how I'd go about creating my own implementation for e.g. Int64 and what have you. – Bent Rasmussen Oct 05 '09 at 15:09
  • It looks like it's the C# compiler than converts this into classes. The CLR has no notion of yield return. I'm also interested in possible compiler optimizations (CLR JIT or C# compiler) on IEnumerables. – Bent Rasmussen Oct 05 '09 at 15:15

4 Answers4

1

You can use Reflector to see the implementation for yourself. It checks arguments and throws exception at the time of calling, so the Range method itself is not an iterator method. It calls another method which is an iterator method. It's not OK to post the exact code due to license restrictions.

Community
  • 1
  • 1
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
1

The accepted answer on this question should give you the answer:

public static class Enumerable {
    public static IEnumerable<int> Range(int start, int count) {
        var end = start + count;
        for(var current = start; current < end; ++current) {
            yield return current;
        }
    }
}

This isn't the exact code, as there is a lot of error checking etc. going on within the Range method, and internally, it calls other methods, however, the quoted code above is the "essence" of the Range routine.

Examining the code in Reflector should provide you with far more information.

Community
  • 1
  • 1
CraigTP
  • 44,143
  • 8
  • 72
  • 99
  • I didn't want the essence, I wanted the precise answer - but I appreciate that this is not possible due to license restrictions. Thanks for the input, I've now used reflector and found the answer. – Bent Rasmussen Oct 05 '09 at 15:08
  • It's more like: `if (!valid) throw exception; else return RangeInternal(...);` in which `RangeInternal` is an iterator. This is an important distinction, since if you call `Range` with invalid arguments, you'll get the exception immediately. If the `Range` method used `yield` directly, you didn't get an exception until you `foreach`ed the collection. – Mehrdad Afshari Oct 05 '09 at 19:02
  • @Mehrdad - That's a very good point that the exception is (potentially) thrown immediately rather than deferred, like the iteration itself. It's what I was alluding to when I mentioned about error checking, but you have described it more clearly. – CraigTP Oct 05 '09 at 19:17
1

A slight but significant difference in the Reflector output (as well as the argument check and extra level of internalisation mentioned in CraigTP's answer and its comments):

public static IEnumerable<int> Range(int start, int count) {
    for(int current = 0; current < count; ++current) {
        yield return start + current;
    }
}

That is, instead of another local variable, they apply an extra addition for every yield.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
1

Is it a yielded for-loop? A custom implementation (IEnumerable, IEnumerator)?

Both :-)


.NET 4

In February 2014, Microsoft put a .NET Source Code browser online. Thus, your question can now be answered with an offical source:

Enumerable.Range performs error checking and then calls the private method RangeIterator, which uses a a yielded for-loop.

The license still does not allow posting the code here, but you can look at it yourself at this link:


.NET Core

.NET Core is licensed under the more permissive MIT license. I am not a lawyer, so I don't know if this means I may copy-and-paste it to StackOverflow or not, but here is the direct link to their Enumerable.Range implementation, which uses a custom RangeIterator object:

Heinzi
  • 167,459
  • 57
  • 363
  • 519