方法解析顺序 [英] Method resolution order

查看:102
本文介绍了方法解析顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有:

public class FooBase
{
    public void Write(byte value)
    {
        //something
    }

    public void Write(int value)
    {
        //something
    }
}

public class Foo : FooBase
{
    public void Write(decimal value)
    {
        //something
    }
}

不是这样的:

        var writer = new Foo();

        writer.Write(5);         //calls Write(decimal) !!
        writer.Write((byte)6);   //calls Write(decimal) !!



将调用write(十进制)的过载。为什么?我怎样才能调用write(INT)或写(字节)?

will call Write(decimal) overload. Why? And how can I call Write(int) or Write(byte) ?

推荐答案

是的,它会做到这一点。这实际上是我的谜题#1 。这是不是真的在这个意义类型推断,它的正常使用 - 这是重载决议。这就是你需要在规范一下。

Yes, it will do that. This is effectively my brainteaser #1. This isn't really type inference in the sense that it's normally used - it's overload resolution. That's where you need to look in the spec.

现在,作家的编译时类型为

Now, the compile-time type of Writer is Foo.

当你调用 writer.Write ,编译器将启动类型为和工作它的方式类型hiearchy直到发现原来在该类型,它可以合法使用你提供的参数来调用声明的方法。只要它的发现之一,它不会再往前走了层次。

When you call writer.Write, the compiler will start with type Foo and work its way up the type hiearchy until it finds a method originally declared in that type that it can legitimately call with the arguments you've given. As soon as it's found one, it doesn't go any further up the hierarchy.

现在,5可以转换为小数(等5之后它被专门转换为字节) - 让 Foo.Write(十进制)是的适用函数成员的为你的方法调用 - 这就是被调用。它甚至没有考虑 FooBase.Write 超载,因为它找到了一个匹配了。

Now, 5 is convertible to decimal (and so is 5 after it's been specifically cast to byte) - so Foo.Write(decimal) is an applicable function member for your method call - and that's what gets called. It doesn't even consider the FooBase.Write overloads, because it's found a match already.

到目前为止,它是合理的 - 这个想法是,添加一个方法为基本类型不应该改变重载现有的代码里子类型不知道这件事。这跌倒有点压倒一切当涉及。让我们稍微改变你的代码 - 我要删除字节的版本,请写(INT)虚拟和覆盖它在

So far, it's reasonable - the idea is that adding a method to the base type shouldn't change overload resolution for existing code where the child type doesn't know about it. This falls down a bit when overriding is involved. Let's change your code slightly - I'm going to remove the byte version, make Write(int) virtual and override it in Foo:

public class FooBase
{
    public virtual void Write(int value)
    {
        //something
    }
}

public class Foo : FooBase
{
    public override void Write(int value)
    {
        //something
    }

    public void Write(decimal value)
    {
        //something
    }
}

现在会是怎样新富(),写(5)吗?它将还是的通话 Foo.Write(十进制) - 因为 Foo.Write(INT)没有的声明的Foo中,仅有的重写的存在。如果您更改覆盖然后它会被调用,因为这则算作一个全新的方法声明。

Now what will new Foo().Write(5) do? It will still call Foo.Write(decimal) - because Foo.Write(int) wasn't declared in Foo, only overridden there. If you change override to new then it will be called, because that then counts as a brand new method declaration.

我认为这方面是违反直觉 - 这是不需要的版本,因为如果你覆盖在子类中的方法,你清楚地知道它的基类。

I think that aspect is counterintuitive - and it's not needed for versioning, as if you're overriding a method in the child class, you clearly know it's in the base class.

的故事的寓意:尽量不要做。到头来你会迷惑人。如果从类派生,不增加新的方法具有相同的名称,但不同的签名,如果你能帮助可能它。

The moral of the story: try not to do this. You'll end up confusing people. If you derive from a class, don't add new methods with the same name but a different signature if you can possibly help it.

这篇关于方法解析顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆