如果泛型类型参数(调用类或调用方法的)受以下约束where T : Base
不会调用 T == Derived 中的新方法,而是调用 Base 中的方法。
为什么类型 T 在方法调用中被忽略,即使它应该在运行时之前已知?
Update:但是,当约束使用像这样的接口时where T : IBase
调用的是Base类中的方法(不是接口中的方法,这也是不可能的)。
因此,这意味着系统实际上能够检测到远远超出类型限制的类型!那么为什么在类类型约束的情况下它不超出类型约束呢?
这是否意味着实现该接口的基类中的方法具有该方法的隐式 override 关键字?
测试代码:
public interface IBase
{
void Method();
}
public class Base : IBase
{
public void Method()
{
}
}
public class Derived : Base
{
public int i = 0;
public new void Method()
{
i++;
}
}
public class Generic<T>
where T : Base
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class GenericWithInterfaceConstraint<T>
where T : IBase
{
public void CallMethod(T obj)
{
obj.Method(); //calls Base.Method()
}
public void CallMethod2<T2>(T2 obj)
where T2 : T
{
obj.Method(); //calls Base.Method()
}
}
public class NonGeneric
{
public void CallMethod(Derived obj)
{
obj.Method(); //calls Derived.Method()
}
public void CallMethod2<T>(T obj)
where T : Base
{
obj.Method(); //calls Base.Method()
}
public void CallMethod3<T>(T obj)
where T : IBase
{
obj.Method(); //calls Base.Method()
}
}
public class NewMethod
{
unsafe static void Main(string[] args)
{
Generic<Derived> genericObj = new Generic<Derived>();
GenericWithInterfaceConstraint<Derived> genericObj2 = new GenericWithInterfaceConstraint<Derived>();
NonGeneric nonGenericObj = new NonGeneric();
Derived obj = new Derived();
genericObj.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod(obj); //calls Base.Method()
Console.WriteLine(obj.i);
genericObj2.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod(obj); //calls Derived.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod2(obj); //calls Base.Method()
Console.WriteLine(obj.i);
nonGenericObj.CallMethod3(obj); //calls Base.Method()
Console.WriteLine(obj.i);
obj.Method(); //calls Derived.Method()
Console.WriteLine(obj.i);
}
}
Output:
0
0
0
0
1
1
1
2
除非使用时dynamic
对象,C# 总是在编译时绑定方法——即使使用泛型时也是如此。虚拟方法调用绑定到虚拟方法槽而不是实现方法,因此当它们在派生类对象上执行时,它们将被定向到派生类实现;虽然槽指向的方法将在运行时确定,但到槽的绑定是在编译时发生的。如果声明了派生类方法new
而不是override
,使用派生类绑定的代码将使用派生类方法,但使用基类绑定的代码将使用基类方法。
要理解为什么会出现这种情况,请想象一下如果不是这样的话。如果上课会发生什么Base
声明一个方法int Foo()
,和一个类Derived:Base
声明一个new string Foo()
。如果一个带有约束的泛型类T:Base
尝试调用方法Foo
在类型的对象上T
,该方法的返回类型应该是什么?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)