我想了解C#如何实现Dictionary。在我看来,Dictionary应该从IEnumerable继承,这需要方法实现:
IEnumerable GetEnumerator()
但是,C#Dictionary实现了:
Dictionary<T>.Enumerator GetEnumerator()
其中Enumerator是一个继承自IEnumerator的嵌套结构。
我已经创建了这种关系的一个例子:
public interface IFoo
{
IFoo GetFoo();
}
public abstract class Foo : IFoo
{
public abstract FooInternal GetFoo();
public struct FooInternal : IFoo
{
public IFoo GetFoo()
{
return null;
}
}
}
但是,这不会编译,导致以下错误:
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
对我在这里做错了什么的想法? C#如何实现字典?如何使示例代码与C#Dictionary类似地编译?
答案 0 :(得分:3)
您缺少明确的接口实现:
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;
}
}
}
答案 1 :(得分:1)
您混淆了两个不同的界面,即 IEnumerable
和IEnumerator
。
外部类(字典类)实现IEnumerable
。这涉及外部类有一个方法GetEnumerator
。此方法返回嵌套(内部)结构的实例。
内部结构实现IEnumerator
。要实施IEnumerator
,您必须拥有MoveNext
方法和Current
属性。
此外,Andrey Shchekin的回答也提到了显式接口实现的问题。此代码是合法的,类似于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
{
}
}
也可以通过公共方法直接实现IFoo
“(非显式),但声明的返回类型必须匹配:
public class Foo : IFoo
{
// public method that directly implements the interface
public IBar GetBar()
{
return new BarInternal();
}
public struct BarInternal : IBar
{
}
}
Dictionary<,>
不是用这种更简单的方式编写的原因是,我猜你会得到嵌套结构的装箱。
请注意,当您foreach
通过Dictionary<,>
时,C#编译器首先搜索具有确切名称GetEnumerator
的公共非通用无参数实例方法。如果找到这样的方法,则使用它,编译器不关心IEnumerable
。因此,使用Dictionary<,>
时,foreach
期间会使用稍微更优化的不实施界面的公共方法。
MSDN上记录了显式接口实现。请参阅Dictionary<TKey, TValue>.IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator
(通用)和Dictionary<TKey, TValue>.IEnumerable.GetEnumerator
(非通用)。