5
  1. I have a generic class A<T>, that implements IEnumerable<T[]>.
  2. I want to have a convenience wrapper B that inherits from A<char> and implements IEnumerable<string>.

    public class A<T> : IEnumerable<T[]> { public IEnumerator<T[]> GetEnumerator() { return Enumerate().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } protected IEnumerable<T[]> Enumerate() { throw new System.NotImplementedException(); } } public class B : A<char>, IEnumerable<string> { public IEnumerator<string> GetEnumerator() { return Enumerate().Select(s => new string(s)).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

Now, this works perfectly fine, foreach variable type is inferred to be string:

B b = new B(); foreach (var s in b) { string[] split = s.Split(' '); } 

But this won't compile, saying "The type arguments cannot be inferred from usage, try specifying the type arguments explicitly":

string[] strings = b.ToArray(); 

However, this works:

string[] strings = b.ToArray<string>(); 

Can anyone explain this compiler behavior?

Obviously, B implements both IEnumerable<char[]> and IEnumerable<string> and probably it can't figure out which of them I want to call, but why it works fine in "foreach" sample?

Please, don't suggest me to solve my problem by composition - this is the last resort for me.

0

2 Answers 2

2

The difference is the following:

foreach actually looks for a public method called GetEnumerator. It doesn't really care for IEnumerable<T>. Your class B only has one public method named GetEnumerator: The one defined in B which hides the one defined in A.

ToArray on the other hand is an extension method on IEnumerable<T>. As your class is both IEnumerable<string> and IEnumerable<char[]> the call is ambiguous between the two generic arguments string and char[].

Sign up to request clarification or add additional context in comments.

Comments

2

foreach loop does not use IEnumerable or IEnumerable<T> implementation. You can use foreach even if your class doesn't implement any of them. The only thing it needs is GetEnumerator method that returns IEnumerator implementation.

Check this question: How is foreach implemented in C#?

That's why your class works with foreach and doesn't with ToArray().

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.