Search code examples
c#listienumerableienumeratorcallermembername

Override the default behaviour of GetEnumerator


I have a requirement where I need to know the calling method to the GetEnumerator().

The best way I could think would be possibly overriding the default behaviour to GetEnumerator to one that I create i.e GetEnumerator([CallerMemberName]string caller = null) but I cannot seem to do this as anything calling it still goes to the original one.

public class MyItems : IEnumerable<string>
{
    private List<string> items = new List<string>();
    public MyItems()
    {
        items.Add("One");
        items.Add("Two");
        items.Add("Three");
        items.Add("Four");
        items.Add("Five");
        items.Add("Six");
    }

    public IEnumerator<string> GetEnumerator()
    {
        return items.GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator([CallerMemberName]string caller = null)
    {
        var method = caller;
        return items.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

Example of some calling code could be

private void button1_click(object sender,EventArgs e)
{
    MyItems items = new MyItems();
    foreach (var item in items)
    {

    }
}

The aim is that I would want to know for example "button1_click" in the GetEnumerator() method


Solution

  • I don't think it's possible to do exactly what you want to do, since foreach, to my knowledge, always calls the GetEnumerator() without any arguments. However, I see two possibilities to your issue

    You can use a StackTrace to get the calling method:

    public IEnumerator<string> GetEnumerator()
    {
        StackTrace stackTrace = new StackTrace();
        Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
        return items.GetEnumerator();
    }
    

    or you can use another method instead of the GetEnumerator() which takes the [CallerMemberName] attribute.

    public IEnumerable<string> Iterate([CallerMemberName]string caller = null)
    {
        Console.WriteLine(caller);
        return items;
    }
    
    foreach (var myItem in items.Iterate())
    {
        //..
    }