Reputation: 1218
I am trying to understand how C# implements the Dictionary. It seems to me that Dictionary is supposed to inherit from IEnumerable which requires the method implementation for:
IEnumerable GetEnumerator()
However, the C# Dictionary instead implements:
Dictionary<T>.Enumerator GetEnumerator()
Where Enumerator is a nested struct which inherits from IEnumerator.
I have created an example of this relationship:
public interface IFoo
{
IFoo GetFoo();
}
public abstract class Foo : IFoo
{
public abstract FooInternal GetFoo();
public struct FooInternal : IFoo
{
public IFoo GetFoo()
{
return null;
}
}
}
However, this doesn't compile, resulting in the following error:
Error 2 'Foo' does not implement interface member 'IFoo.GetFoo()'. 'Foo.GetFoo()' cannot implement 'IFoo.GetFoo()' because it does not have the matching return type of 'CodeGenerator.UnitTests.IFoo'. Foo.cs 14
Any thoughts on what I might be doing wrong here? How does C# implement the Dictionary? How would one make the example code compile similarly to the C# Dictionary?
Upvotes: 0
Views: 735
Reputation: 61952
You are confusing two distinct interfaces, namely IEnumerable
and IEnumerator
.
The outer class, the dictionary class, implements IEnumerable
. This involves that the outer class has a method GetEnumerator
. This method returns an instance of the nested (inner) struct.
The inner struct implements IEnumerator
. To implement IEnumerator
you must have a MoveNext
method and a Current
property.
Besides, there's the issue of explicit interface implementation which is mentioned also by Andrey Shchekin's answer. This code is legal and similar to Dictionary<,>
:
public interface IFoo // corresponds to IEnumerable
{
IBar GetBar();
}
public interface IBar // corresponds to IEnumerator
{
}
public class Foo : IFoo
{
// public method that has BarInternal as return type
public BarInternal GetBar()
{
return new BarInternal();
}
// explicit interface implementation which calls the public method above
IBar IFoo.GetBar()
{
return GetBar();
}
public struct BarInternal : IBar
{
}
}
It would also be possible to implement the IFoo
"directly" (not explicitly) by a public method, but then the declared return type must match:
public class Foo : IFoo
{
// public method that directly implements the interface
public IBar GetBar()
{
return new BarInternal();
}
public struct BarInternal : IBar
{
}
}
The reason why Dictionary<,>
isn't written in this simpler way, is that you get boxing of the nested struct, I guess.
Note that when you foreach
through a Dictionary<,>
, the C# compiler first searches for a public non-generic parameterless instance method with the exact name GetEnumerator
. If such a method is found, it is used, and the compiler doesn't care about IEnumerable
. Therefore, with a Dictionary<,>
, the slightly more optimal public method which does not implement the interface, is used during foreach
.
Explicit interface implementations are documented on MSDN. See Dictionary<TKey, TValue>.IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator
(generic) and Dictionary<TKey, TValue>.IEnumerable.GetEnumerator
(non-generic).
Upvotes: 1
Reputation: 21599
You are missing an explicit interface implementation:
public abstract class Foo : IFoo
{
public abstract FooInternal GetFoo();
// start here
IFoo IFoo.GetFoo()
{
return GetFoo();
}
// end here
public struct FooInternal : IFoo
{
public IFoo GetFoo()
{
return null;
}
}
}
Upvotes: 3