在外部库中绑定到基本方法的方法无法处理"之间"的新虚拟方法

Ber*_*erg 10 c#

假设我有一个1.0.0版的库,其中包含以下内容:

public class Class1
{
    public virtual void Test()
    {
        Console.WriteLine( "Library:Class1 - Test" );
        Console.WriteLine( "" );
    }
}
public class Class2 : Class1
{
}
Run Code Online (Sandbox Code Playgroud)

我在控制台应用程序中引用此库,其中包含以下内容:

class Program
{
    static void Main( string[] args )
    {
        var c3 = new Class3();
        c3.Test();
        Console.ReadKey();
    }
}
public class Class3 : ClassLibrary1.Class2
{
    public override void Test()
    {
        Console.WriteLine("Console:Class3 - Test");
        base.Test();
    }
}
Run Code Online (Sandbox Code Playgroud)

运行该程序将输出以下内容:

Console:Class3 - Test
Library:Class1 - Test
Run Code Online (Sandbox Code Playgroud)

如果我构建一个新版本的库,版本2.0.0,看起来像这样:

public class Class1
{
    public virtual void Test()
    {
        Console.WriteLine( "Library:Class1 - Test V2" );
        Console.WriteLine( "" );
    }
}

public class Class2 : Class1
{
    public override void Test()
    {
        Console.WriteLine("Library:Class2 - Test V2");
        base.Test();
    }
}
Run Code Online (Sandbox Code Playgroud)

并将此版本复制到包含我的控制台程序的bin文件夹并运行它,结果是:

Console:Class3 - Test
Library:Class1 - Test V2
Run Code Online (Sandbox Code Playgroud)

即,从不执行Class2.Test方法,Class3.Test中的base.Test调用似乎绑定到Class1.Test,因为在编译控制台程序时Class2.Test不存在.这对我来说非常令人惊讶,在没有重新编译应用程序的情况下部署新版本的库的情况下可能会出现一个大问题.

有没有其他人有这方面的经验?

有什么好的解决方案吗?

这使得很有可能添加只调用base的空覆盖,以防我将来需要在该级别添加一些代码...

编辑:

似乎已确定调用在编译时绑定到第一个现有的基本方法.我想知道为什么.如果我构建我的控制台程序时引用我的库的第2版(这应该意味着编译调用以调用Class2.Test)然后将bin文件夹中的dll替换为版本1,结果是,如预期的那样:

Console:Class3 - Test
Library:Class1 - Test
Run Code Online (Sandbox Code Playgroud)

因此,当Class2.Test不存在时,没有运行时错误.为什么基本调用不能编译为首先调用Class2.Test?

从Eric Lippert或与编译器合作的其他人那里得到评论会很有趣......

Eri*_*ert 12

这是我博客3月29日的主题:

http://blogs.msdn.com/ericlippert/archive/2010/03/29/putting-a-base-in-the-middle.aspx

事实证明,C#1.0是按照你的方式做到的,并且这个决定会导致一些有趣的崩溃和性能问题.我们将其转换为C#2.0中的新方式.

我从这个问题中学到了很多东西.有关详细信息,请参阅博客