Bac*_*ave 5 c# generics inheritance
有人可以向我解释为什么下面的代码会输出它的作用吗?为什么T是一个字符串在第一个,而不是Int32,为什么在下一个输出中它是相反的情况?
这个谜题来自对Eric Lippert的采访
当我浏览代码时,我真的不知道它是Int32还是String:
public class A<T>
{
public class B : A<int>
{
public void M() { System.Console.WriteLine(typeof(T)); }
public class C : B { }
}
}
public class P
{
public static void Main()
{
(new A<string>.B()).M(); //Outputs System.String
(new A<string>.B.C()).M(); //Outputs System.Int32
Console.Read();
}
}
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么下面的代码会输出它的作用吗?
问题的关键在于确定Bin 的含义class C : B.考虑一个没有泛型的版本:(为简洁起见,我将省略公众.)
class D { class E {} }
class J {
class E {}
class K : D {
E e; // Fully qualify this type
}
}
Run Code Online (Sandbox Code Playgroud)
那可能是J.E或D.E; 这是什么?解析名称时C#中的规则是查看基类层次结构,只有当它失败时,才能查看容器.K已经通过继承拥有成员E,因此不需要查看其容器以发现其容器具有包含成员E.
但是我们看到这个谜题具有相同的结构; 它只是被仿制药混淆了.我们可以像处理模板那样处理泛型,只需将A-of-string和A-of-int的结构写成类:
class A_of_int
{
class B : A_of_int
{
void M() { Write("int"); }
class C : B { } // A_of_int.B
}
}
class A_of_string
{
class B : A_of_int
{
void M() { Write("string"); }
class C : B {} // still A_of_int.B
}
}
Run Code Online (Sandbox Code Playgroud)
现在应该清楚为什么A_of_string.B.M()写string但A_of_string.B.C.M()写int.
小智 2
稍微改变一下代码:
public class A<T>
{
public class B : A<int>
{
public void M() { System.Console.WriteLine(typeof(T)); }
public class C : A<T>.B { }
}
}
public class P
{
public static void Main()
{
(new A<string>.B.C()).M(); //Outputs System.String
}
}
Run Code Online (Sandbox Code Playgroud)
请注意我如何将C基类从更改B为A<T>.B。这会将输出从 更改System.Int32为System.String。
如果没有它,A<string>.B.C不是从 派生A<string>.B,而是从 派生A<int>.B,导致您所看到的行为。这是因为,一般来说,基类中定义的名称可以通过非限定查找来获得,并且该名称B是在基类中定义的A<int>。