假设我有一个库,版本 1.0.0,包含以下内容:
public class Class1
{
public virtual void Test()
{
Console.WriteLine( "Library:Class1 - Test" );
Console.WriteLine( "" );
}
}
public class Class2 : Class1
{
}
我在控制台应用程序中引用该库,内容如下:
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();
}
}
运行程序将输出以下内容:
Console:Class3 - Test
Library:Class1 - Test
如果我构建一个新版本的库,版本 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();
}
}
并将这个版本复制到包含我的控制台程序的bin文件夹中并运行它,结果是:
Console:Class3 - Test
Library:Class1 - Test V2
即,Class2.Test 方法永远不会执行,Class3.Test 中的 base.Test 调用似乎绑定到 Class1.Test,因为编译控制台程序时 Class2.Test 不存在。
这让我感到非常惊讶,并且在您部署新版本的库而不重新编译应用程序的情况下可能会成为一个大问题。
还有其他人有这方面的经验吗?
有什么好的解决办法吗?
这使得添加仅调用 base 的空覆盖很诱人,以防我将来需要在该级别添加一些代码......
Edit:
似乎可以确定该调用在编译时绑定到第一个现有的基本方法。我想知道为什么。如果我使用对库版本 2 的引用来构建控制台程序(这应该意味着该调用被编译为调用 Class2.Test ),然后用版本 1 替换 bin 文件夹中的 dll,结果将如预期的那样:
Console:Class3 - Test
Library:Class1 - Test
因此,当 Class 2.Test 不存在时,不会出现运行时错误。为什么不能首先编译基调用来调用 Class 2.Test?
从 Eric Lippert 或其他使用编译器的人那里得到评论会很有趣......