嵌套调用中的C#重载
鉴于以下情况:嵌套调用中的C#重载,c#,overloading,C#,Overloading,鉴于以下情况: class A { public void Foo(object o) { Console.WriteLine("general"); } public void Foo(B o) { Console.WriteLine("specific"); } } class B { A a = new A(); public void CallFoo(object x) {
class A
{
public void Foo(object o)
{
Console.WriteLine("general");
}
public void Foo(B o)
{
Console.WriteLine("specific");
}
}
class B
{
A a = new A();
public void CallFoo(object x)
{
a.Foo(x);
}
public static void Main()
{
B b = new B();
b.CallFoo(b);
b.a.Foo(b);
}
}
我观察到以下结果:
general
specific
很自然,我很困惑。这里发生了什么?每一个
b.CallFoo
都将导致打印general,因为CallFoo
将对象
作为参数。正确的方法重载是在编译过程中确定的,因此这里编译器只能选择常规方法
通过使用dynamic
asCallFoo
参数类型,可以在运行时强制选择重载:
public void CallFoo(dynamic x)
{
a.Foo(x);
}
或者您可以自己编写逻辑,在B.CallFoo
中:
public void CallFoo(object x)
{
if (x is B)
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public void Foo(object o)
{
if (o is B)
{
Foo((B)o);
}
else
{
Console.WriteLine("general");
}
}
或者直接在a.Foo
中:
public void CallFoo(object x)
{
if (x is B)
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public void Foo(object o)
{
if (o is B)
{
Foo((B)o);
}
else
{
Console.WriteLine("general");
}
}
每个
b.CallFoo
都将导致打印general,因为CallFoo
将object
作为参数。正确的方法重载是在编译过程中确定的,因此这里编译器只能选择常规方法
通过使用dynamic
asCallFoo
参数类型,可以在运行时强制选择重载:
public void CallFoo(dynamic x)
{
a.Foo(x);
}
或者您可以自己编写逻辑,在B.CallFoo
中:
public void CallFoo(object x)
{
if (x is B)
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public void Foo(object o)
{
if (o is B)
{
Foo((B)o);
}
else
{
Console.WriteLine("general");
}
}
或者直接在a.Foo
中:
public void CallFoo(object x)
{
if (x is B)
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public void Foo(object o)
{
if (o is B)
{
Foo((B)o);
}
else
{
Console.WriteLine("general");
}
}
这绝对是正确的行为。重载解析通常发生在编译时,而不是运行时。(除非您正在进行一些时髦的反射或编译lambda表达式) 在代码中,.NET在编译时只知道x是一个对象:
public void CallFoo(object x)
{
a.Foo(x); // <--- Gets wired up to Foo(object o) as x is declared as an object!
}
public void CallFoo(对象x)
{
a、 Foo(x);//这绝对是正确的行为。重载解析通常发生在编译时,而不是运行时。(除非您正在进行一些时髦的反射或编译lambda表达式)
在代码中,.NET在编译时只知道x是一个对象:
public void CallFoo(object x)
{
a.Foo(x); // <--- Gets wired up to Foo(object o) as x is declared as an object!
}
public void CallFoo(对象x)
{
a、 Foo(x);//b.CallFoo(对象x)
正在作为对象的类型传递
如果不选中instanceof,它将被视为对象类型
如果将A.Foo的功能更改为:
public void Foo(object o){
B test = o as B;
if(test == null){
Console.WriteLine("general");
}else
{
Console.WriteLine("specific");
}
}
你将得到你所期望的b.CallFoo(对象x)
正在作为对象的类型传递
如果不选中instanceof,它将被视为对象类型
如果将A.Foo的功能更改为:
public void Foo(object o){
B test = o as B;
if(test == null){
Console.WriteLine("general");
}else
{
Console.WriteLine("specific");
}
}
您将得到您所期望的这是期望的行为。在您的第一次调用b.CallFoo(b)
中,您正在调用方法b.CallFoo(object)
,该方法反过来调用基类的Foo(object)
在第二次调用中,您直接从类A访问Foo(B)
方法,并且还传递类型为B的var B,这是预期的行为。在第一次调用B.CallFoo(B)
中,您调用的是方法B.CallFoo(object)
,该方法反过来调用基类的Foo(对象)
在第二个调用中,您直接从类A访问Foo(B)
方法,并且还传递类型为B的var B,这都是关于方法签名的。B.CallFoo()接受一个对象,自然地,它调用期望对象的重载。下一个调用是输入一个类型为B的强类型对象,编译器知道您想要使用接受类型为B的对象的重载
如果希望根据类型有条件地调用重载,则必须自己完成这项工作
例如:
class B
{
A a = new A();
public void CallFoo(object x)
{
if (x.GetType() == typeof(B))
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public static void Main()
{
B b = new B();
b.CallFoo(b);
b.a.Foo(b);
}
}
这都是关于方法签名的。b.CallFoo()接受一个对象,自然,它调用期望对象的重载。下一个调用是输入一个类型为b的强类型对象,编译器知道您想要使用接受类型为b的对象的重载
如果希望根据类型有条件地调用重载,则必须自己完成这项工作
例如:
class B
{
A a = new A();
public void CallFoo(object x)
{
if (x.GetType() == typeof(B))
{
a.Foo((B)x);
}
else
{
a.Foo(x);
}
}
public static void Main()
{
B b = new B();
b.CallFoo(b);
b.a.Foo(b);
}
}
1) b.CallFoo(b);
CallFoo将对象类型作为参数。然后将该对象传递给Foo,从而调用Foo(对象o)
2) b.a.Foo(b);
Foo(bo)将被调用,因为传递的对象的类型为B。1)B.CallFoo(B);
CallFoo将对象类型作为参数。然后将该对象传递给Foo,从而调用Foo(对象o)
2) b.a.Foo(b);
Foo(bo)将被调用,因为传递的对象是类型B。对我来说似乎很明显。CallFoo
采用对象参数,因此a.Foo(x)
将解析为Foo(object)
B.a.Foo(B)
可以调用Foo(B)
因为大家都知道b在那里总是b型的。我也不确定这里是否有问题……对我来说似乎很明显。CallFoo
接受一个object参数,因此a.Foo(x)
将解析为Foo(object)
b.a.Foo(b)
可以调用Foo(b)
因为我们知道b总是b类型。我也不确定这里是否有问题。这正是我不理解的地方——重载的编译时解析。不幸的是,在这种情况下,由于交叉编译问题,我不能将x定义为动态的。所以……我必须使用“is”构造,这正是我试图避免的。谢谢!这正是我不理解的一点——重载的编译时解析。不幸的是,在这种情况下,由于交叉编译问题,我不能将x定义为动态的。所以…我必须使用“is”构造,这正是我试图避免的。谢谢!