我不明白为什么以下行为完全按照它的方式行事。我甚至不知道它是由隐藏还是其他原因造成的。
class A<T>
{
public class B : A<int>
{
public void b()
{
Console.WriteLine(typeof(T).ToString());
}
public class C : B
{
public void c()
{
Console.WriteLine(typeof(T).ToString());
}
}
public class D : A<T>.B
{
public void d()
{
Console.WriteLine(typeof(T).ToString());
}
}
}
}
class Program
{
static void Main(string[] args)
{
A<string>.B.C c = new A<string>.B.C();
A<string>.B.D d = new A<string>.B.D();
c.c();
c.b();
d.d();
d.b();
}
}
问题是:
为什么c.c()
生成System.String而c.b()
生成System.Int32
?
为什么d.d()
和d.b()
都会生成System.String
而行为与C
类的行为完全相同?
答案 0 :(得分:11)
这是我多年前在我的博客上发布的一个谜题的变体:
http://blogs.msdn.com/b/ericlippert/archive/2007/07/27/an-inheritance-puzzle-part-one.aspx
和Cyrus之前在他的博客上发布了:
http://blogs.msdn.com/b/cyrusn/archive/2005/08/01/446431.aspx
请参阅那里的讨论以获取详细信息。
简要说明B
在class C : B
中的含义是什么?检查容器class B
。它是否包含任何名为B
的类型?不。然后检查容器的基类。容器的基类是A<int>
。它是否包含任何名为B
的内容?是。所以这意味着class C : A<int>.B
。
现在我们说c
是A<string>.B.C
。我们称之为方法A<string>.B.C.c()
T
中的A<string>
是什么?显然是string
。因此c.c()
为String
打印T
。
现在我们致电A<string>.B.C.b()
,但A<string>.B.C
中没有这样的方法。它在哪里获得这种方法?从它的基础类。什么是基类? A<int>.B
。所以我们打电话给A<int>.B.b()
。整个T
的{{1}}是什么?显然是A<int>
。
现在我们来int
。基类是无关紧要的。 A<string>.B.D.d()
T
string
A<string>
。
最后A<string>.B.D.b()
。 A<string>.B.D
上没有这样的方法,所以必须从它的基类型中获取它。 T
string
在整个A<string>
中都是A<string>.B
,因此基本类型为A<string>.B.b()
。因此,这会调用class A_string
{
public class B : A_int
{
public void b()
{
Console.WriteLine(typeof(string).ToString());
}
public class C : A_int.B // Note!
{
public void c()
{
Console.WriteLine(typeof(string).ToString());
}
}
public class D : A_string.B
{
public void d()
{
Console.WriteLine(typeof(string).ToString());
}
}
}
}
。
如果这对你没有意义,请拼出一切。让我们用String代替T:
class A_int
{
public class B : A_int
{
public void b()
{
Console.WriteLine(typeof(int).ToString());
}
public class C : A_int.B // Note!
{
public void c()
{
Console.WriteLine(typeof(int).ToString());
}
}
public class D : A_int.B
{
public void d()
{
Console.WriteLine(typeof(int).ToString());
}
}
}
}
好的,这是其中一种类型。现在让我们对int执行相同的操作:
A_string.B.C.c()
现在给出这些类型,应该清楚显示A_string.B.C.b()
,{{1}}等所有内容。
答案 1 :(得分:3)
A<string>.B.C
继承A<int>.B
,因为基类声明中的B
首先来自内部父作用域。 (澄清一下,其父作用域为A<T>.B
,其中包含一个名为B
的类型,引用A<int>.B
,继承自其基类A<int>
)
调用b()
来自其基类,其中T
(来自父作用域)为int
。
D
使用A<T>.B
从最外层范围(T
)明确继承A<T>
,因此其T
始终来自A<>
in它的类型名称。
答案 2 :(得分:3)
这是Eric Lippert在this blog article中描述的谜题的一个稍微复杂的例子,然后在this article中进行了解释。
简短摘要(我强烈建议阅读本文)是在这种情况下,行C : B
中存在歧义。需要做出关于B
在这种情况下实际意味着什么的决定;是A<T>.B
还是A<int>.B
。基本上,编译器选择后者,给出规范中描述的“更好”的特定标准。