给出以下协变通用接口
public interface IContainer<out T>
{
T Value { get; }
}
我们可以为多个泛型类型创建一个多次实现此接口的类。在我感兴趣的场景中,这些泛型类型共享一个共同的基类型。
public interface IPrint
{
void Print();
}
public class PrintA : IPrint
{
public void Print()
{
Console.WriteLine("A");
}
}
public class PrintB : IPrint
{
public void Print()
{
Console.WriteLine("B");
}
}
public class SuperContainer : IContainer<PrintA>, IContainer<PrintB>
{
PrintA IContainer<PrintA>.Value => new PrintA();
PrintB IContainer<PrintB>.Value => new PrintB();
}
现在通过IContainer<IPrint>
类型的引用使用此类时,事情变得有趣。
public static void Main(string[] args)
{
IContainer<IPrint> container = new SuperContainer();
container.Value.Print();
}
编译并运行没有问题并打印&#34; A&#34;。我在spec:
中找到了什么我所在的特定接口成员I.M的实现 声明成员M的接口由下式确定 检查每个类或结构S,从C开始并重复 C的每个连续基类,直到找到匹配:
- 如果是S. 包含显式接口成员实现的声明 匹配I和M,那么这个成员就是I.M。
的实现- 否则,如果S包含非静态公共成员的声明 匹配M,那么这个成员就是I.M。
的实现
第一个要点似乎是相关的,因为接口实现是显式的。但是,当有多个候选人时,它没有说明选择了哪个实现。
如果我们使用公共属性来实现IContainer<PrintA>
,那就更有趣了:
public class SuperContainer : IContainer<PrintA>, IContainer<PrintB>
{
public PrintA Value => new PrintA();
PrintB IContainer<PrintB>.Value => new PrintB();
}
现在,根据上面的规范,因为通过IContainer<PrintB>
有一个明确的界面实现,我希望这可以打印&#34; B&#34;。但是,它改为使用公共财产并仍然打印&#34; A&#34;。
同样,如果我通过公共财产明确地实施IContainer<PrintA>
和IContainer<PrintB>
,它仍会打印&#34; A&#34;。
看来输出所依赖的唯一依据是声明接口的顺序。如果我将声明更改为
public class SuperContainer : IContainer<PrintB>, IContainer<PrintA>
一切都打印出来&#34; B&#34;!
规范的哪一部分定义了此行为,如果它已正确定义?
答案 0 :(得分:0)
我无法在规范中找到它,但您所看到的是预期的。 IContainer<PrintA>
和IContainer<PrintB>
具有不同的完全限定名称(无法找到关于如何形成此FQN的规范),因此编译器将SuperContainer
识别为两个不同接口的实现类,每个接口都有一个void Print();
方法。
因此,我们有两个不同的接口,每个接口都包含一个具有相同签名的方法。当您在spec (13.4.2)中链接时,首先通过查看Print()
,查找正确的映射,然后然后查看{{1}来选择IContainer<PrintA>
的实现。 }}
由于IContainer<PrintB>
中找到了正确的映射,因此IContainer<PrintA>
IContainer<PrintA>.Print()
的{{1}}使用了SuperContainer
。
从同一规范(位于最底层):
基类的成员参与接口映射。在示例中
IContainer<PrintB>
Class1中的方法F用于Class2的Interface1实现。
所以最后,是的顺序是确定调用哪个interface Interface1
{
void F();
}
class Class1
{
public void F() {}
public void G() {}
}
class Class2: Class1, Interface1
{
new public void G() {}
}
方法。