简体   繁体   中英

IEnumerable<T> in C#

I am trying to get the following code to compile but am getting errors in VS2008. Anyone can tell me where I am going wrong?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace dummy
{
    public class NaturalNumbersSequence : IEnumerable<int>
    {
        public IEnumerator<int> GetEnumerator()
        {
            for (int i = 1; i <= 1000; i++)
                yield return i;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            for (int i = 1; i <= 1000; i++)
                yield return i;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            foreach (int i in new NaturalNumbersSequence())
                Console.WriteLine(i);
        }
    }
}

Well, the first compiler error I get is that it complains that:

Using the generic type 'System.Collections.Generic.IEnumerator' requires '1' type arguments

This is on line 16, this one:

IEnumerator IEnumerable.GetEnumerator()

Fixing that by adding a using directive for the System.Collections namespace (tip: place the cursor just after IEnumerator, on the r at the end of the word, and hit Ctrl+. (ctrl + the dot-key), it should suggest you add a "using System.Collections;" directive, do that).

Then it compiles, and runs. Does that match what you expect?

Also, note that you should always post the actual error messages you're getting, this way we're not barking up the wrong tree if there's something else wrong with your code that we're not seeing at first glance.

Additionally, you can simplify this very common implementation of IEnumerable<T> by calling one of the methods from the other, hence I would simplify the implementation of the second methods like this:

IEnumerator IEnumerable.GetEnumerator()
{
    return GetEnumerator(); // this will return the one
                            // available through the object reference
                            // ie. "IEnumerator<int> GetEnumerator"
}

this way you only implement the actual enumerator code once.

And finally see Earwicker 's answer as well, it shows a better (in my opinion at least) way to write this whole code.

Not sure why you're getting errors, but wouldn't this be simpler?

public static class NumbersSequence
{
    public static IEnumerable<int> Naturals
    {
        get 
        {
            for (int i = 1; i <= 1000; i++)
                yield return i;
        }
    }
}

class Program
{
    public static void Main(string[] args)
    {
        foreach (int i in NumbersSequence.Naturals)
            Console.WriteLine(i);
    }
}

Slightly off-topic, but perhaps interesting to see is this approach:

public static class NumbersSequence
{
    public static IEnumerable<int> Naturals
    {
        get 
        {
            int i = 0;
            while(true)
                yield return i++;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        foreach (int i in NumbersSequence.Naturals.Take(1000))
            Console.WriteLine(i);
    }
}

C# 3.0 afaik. Pay attention to the seemingly endless loop in the getter, and the call to Take(1000). With this method you now have an 'endless' sequence of natural numbers (endless up until the maxvalue of an int). It won't get stuck, as long as you tell it to take a specific amount.

DISCLAIMER: Most of the code borrowed from Earwicker's answer.

Lasse has the right answer, and I know this is learning code, but in the interest of furthering your learning I want to mention two things:

  1. Enumerable.Range()
  2. Take some time to think about this implementation:

.

public class NaturalNumbersSequence : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        for (int i=0 i <= int.MaxValue;i++)
            yield return i;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        for (int i=0 i <= int.MaxValue;i++)
            yield return i;
    }
}

class Program
{
    static void Main(string[] args)
    {
        foreach (int i in new NaturalNumbersSequence().TakeWhile(i => i<=1000) )
            Console.WriteLine(i);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM