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.
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[]
.
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With