gpt4 book ai didi

c# - C# 语言规范是否指定是使用方法覆盖还是使用影子?

转载 作者:行者123 更新时间:2023-11-30 16:07:01 26 4
gpt4 key购买 nike

考虑以下源代码:

public abstract class SomeBaseClass {

public abstract void Foo(object a);

}

public class SomeClass<T> : SomeBaseClass {

public override void Foo(object a) {
Console.WriteLine("Foo() from SomeBaseClass");
}

public void Foo(T a) {
Console.WriteLine("Foo() from SomeClass");
}

}

由于 Foo 有两个重载,因此以下内容一点也不含糊:

public class Bar : SomeClass<int> { }

var bar = new Bar();
bar.Foo(null);
bar.Foo(24);

C# 语言规范是否说明了以下以某种方式编译的示例中的预期行为?

public class Baz : SomeClass<object> { }

var baz = new Baz();
baz.Foo(null); // "Foo() from SomeClass"

最佳答案

检查这个strange behavior explained by Jon Skeet in his blog post Overloading

Inheritance can cause a confusing effect. When the compiler goes looking for instance method overloads, it considers the compile-time class of the "target" of the call, and looks at methods declared there. If it can't find anything suitable, it then looks at the parent class... then the grandparent class, etc. This means that if there are two methods at different levels of the hierarchy, the "deeper" one will be chosen first, even if it isn't a "better function member" for the call. Here's a fairly simple example:

using System;

class Parent
{
public void Foo(int x)
{
Console.WriteLine("Parent.Foo(int x)");
}
}

class Child : Parent
{
public void Foo(double y)
{
Console.WriteLine("Child.Foo(double y)");
}
}


class Test
{
static void Main()
{
Child c = new Child();
c.Foo(10);
}
}

The target of the method call is an expression of type Child, so the compiler first looks at the Child class. There's only one method there, and it's applicable (there's an implicit conversion from int to double) so that's the one that gets picked. The compiler doesn't consider the Parent method at all.

The reason for this is to reduce the risk of the brittle base class problem, where the introduction of a new method to a base class could cause problems for consumers of classes derived from it. Eric Lippert has various posts about the brittle base class problem which I can highly recommend.

There's one aspect of this behaviour which is particularly surprising though. What counts as a method being "declared" in a class? It turns out that if you override a base class method in a child class, that doesn't count as declaring it. Let's tweak our example very slightly:

using System;

class Parent
{
public virtual void Foo(int x)
{
Console.WriteLine("Parent.Foo(int x)");
}
}

class Child : Parent
{
public override void Foo(int x)
{
Console.WriteLine("Child.Foo(int x)");
}

public void Foo(double y)
{
Console.WriteLine("Child.Foo(double y)");
}
}


class Test
{
static void Main()
{
Child c = new Child();
c.Foo(10);
}
}

Now it looks like you're trying to call Child.Foo(int x) in my opinion - but the above code will actually print Child.Foo(double y). The compiler ignores the overriding method in the child.

Given this oddness, my advice would be to avoid overloading across inheritance boundaries...

关于c# - C# 语言规范是否指定是使用方法覆盖还是使用影子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31310541/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com