How to use foreach keyword on custom Objects in C#

后端 未结 3 454
鱼传尺愫
鱼传尺愫 2020-12-14 07:49

Can someone share a simple example of using the foreach keyword with custom objects?

相关标签:
3条回答
  • 2020-12-14 08:23

    Given the tags, I assume you mean in .NET - and I'll choose to talk about C#, as that's what I know about.

    The foreach statement (usually) uses IEnumerable and IEnumerator or their generic cousins. A statement of the form:

    foreach (Foo element in source)
    {
        // Body
    }
    

    where source implements IEnumerable<Foo> is roughly equivalent to:

    using (IEnumerator<Foo> iterator = source.GetEnumerator())
    {
        Foo element;
        while (iterator.MoveNext())
        {
            element = iterator.Current;
            // Body
        }
    }
    

    Note that the IEnumerator<Foo> is disposed at the end, however the statement exits. This is important for iterator blocks.

    To implement IEnumerable<T> or IEnumerator<T> yourself, the easiest way is to use an iterator block. Rather than write all the details here, it's probably best to just refer you to chapter 6 of C# in Depth, which is a free download. The whole of chapter 6 is on iterators. I have another couple of articles on my C# in Depth site, too:

    • Iterators, iterator blocks and data pipelines
    • Iterator block implementation details

    As a quick example though:

    public IEnumerable<int> EvenNumbers0To10()
    {
        for (int i=0; i <= 10; i += 2)
        {
            yield return i;
        }
    }
    
    // Later
    foreach (int x in EvenNumbers0To10())
    {
        Console.WriteLine(x); // 0, 2, 4, 6, 8, 10
    }
    

    To implement IEnumerable<T> for a type, you can do something like:

    public class Foo : IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            yield return "x";
            yield return "y";
        }
    
        // Explicit interface implementation for nongeneric interface
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator(); // Just return the generic version
        }
    }
    
    0 讨论(0)
  • 2020-12-14 08:44

    (I assume C# here)

    If you have a list of custom objects you can just use the foreach in the same way as you do with any other object:

    List<MyObject> myObjects = // something
    foreach(MyObject myObject in myObjects)
    {
         // Do something nifty here
    }
    

    If you want to create your own container you can use the yield keyword (from .Net 2.0 and upwards I believe) together with the IEnumerable interface.

    class MyContainer : IEnumerable<int>
    {
        private int max = 0;
        public MyContainer(int max)
        {
            this.max = max;
        }
    
        public IEnumerator<int> GetEnumerator()
        {
            for(int i = 0; i < max; ++i)
                yield return i;
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

    And then use it with foreach:

    MyContainer myContainer = new MyContainer(10);
    foreach(int i in myContainer)
        Console.WriteLine(i);
    
    0 讨论(0)
  • 2020-12-14 08:45

    From MSDN Reference:

    The foreach statement is not limited to IEnumerable types and can be applied to an instance of any type that satisfies the following conditions:

    has the public parameterless GetEnumerator method whose return type is either class, struct, or interface type, the return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.

    If you declare those methods, you can use foreach keyword without IEnumerable overhead. To verify this, take this code snipped and see that it produces no compile-time error:

    class Item
    {
        public Item Current { get; set; }
        public bool MoveNext()
        {
            return false;
        }
    }
    
    class Foreachable
    {
        Item[] items;
        int index;
        public Item GetEnumerator()
        {
            return items[index];
        }
    }
    
    Foreachable foreachable = new Foreachable();
    foreach (Item item in foreachable)
    {
    
    }
    
    0 讨论(0)
提交回复
热议问题