Is it possible to implement multiple IEnumerable <T> in one class?

I want to do something like this:

class T : IEnumerable<string>, IEnumerable<int> { string [] _strings = new string [20]; int[] _ints = new int[20]; public T() { } IEnumerator<string> IEnumerable<string>.GetEnumerator() { foreach (string str in _strings) yield return str; } IEnumerator<int> IEnumerable<int>.GetEnumerator() { foreach (int i in _ints) yield return i; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } //Using in code: T t = new T(); foreach (int i in t) //to do something foreach (string str in t) //to do stuff 

I want to know if there is a way to implement this or not. Maybe there are tricks?

+4
source share
2 answers

You almost managed to implement both interfaces - you just need to change the non-generic implementation to show which universal implementation you are trying to delegate. For instance:

 IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<int>)this).GetEnumerator(); } 

However, since you are implementing more than one IEnumerable<T> interface, you need to include foreach in the loop to show which one to use:

 T t = new T(); foreach (int i in (IEnumerable<int>) t) //to do something foreach (string str in (IEnumerable<string>) t) 

Personally, I would strongly advise doing this if possible, although this can cause a lot of confusion for people reading your code.

See section 8.8.4 of the C # language specification for details on how the compiler processes an expression to iterate in a foreach .

(Using a β€œnormal” interface implementation for one of the interfaces, you could provide a kind of β€œdefault”, but I don’t think that would really improve.)

+7
source

I would suggest defining some types of structures, the only field of which is an instance of your class type, initialized by the stuct constructor, whose only public member is GetEnumerator and which implements IEnumerable <whatever> by calling the appropriate method in your base type. Then ask your root class to implement an element that returns a new instance of the corresponding structure.

For example, if your Foo class had a GetStringEnumerator method that returned a type that implements IEnumerable <String>, you could have Foo.AsStrings return a FooStringEnumerable structure whose GetEnumerator method is called Foo.GetStringEnumerator.

Please note that if your enumerable thing is a structure and not a class, you will not have to create an additional instance of the object in the general case when it is used in the "for each" loop, since both vb and C # will be a duck-type of the GetEnumerator method instead of pouring in IEnumerable or IEnumerable <T>.

0
source

All Articles