File: Emit\BinaryCompatibility.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit\Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public class BinaryCompatibility : EmitMetadataTestBase
    {
        [Fact]
        public void InvokeVirtualBoundToOriginal()
        {
            // A method invocation of a virtual method is statically bound by the C# language to
            // the original declaration of the virtual method, not the most derived override of
            // that method. The difference between these two choices is visible in the binary
            // compatibility behavior of the program at runtime (e.g. when executing the program
            // against a modified library). This test checks that we bind the invocation to the
            // virtual method, not the override.
            var lib0 = @"
public class Base
{
    public virtual void M() { System.Console.WriteLine(""Base0""); }
}
public class Derived : Base
{
    public override void M() { System.Console.WriteLine(""Derived0""); }
}
";
            var lib0Image = CreateCompilationWithMscorlib46(lib0, options: TestOptions.ReleaseDll, assemblyName: "lib").EmitToImageReference();
 
            var lib1 = @"
public class Base
{
    public virtual void M() { System.Console.WriteLine(""Base1""); }
}
public class Derived : Base
{
    public new virtual void M() { System.Console.WriteLine(""Derived1""); }
}
";
            var lib1Image = CreateCompilationWithMscorlib46(lib1, options: TestOptions.ReleaseDll, assemblyName: "lib").EmitToImageReference();
 
            var client = @"
public class Client
{
    public static void M()
    {
        Derived d = new Derived();
        d.M();
    }
}
";
            var clientImage = CreateCompilationWithMscorlib46(client, references: new[] { lib0Image }, options: TestOptions.ReleaseDll).EmitToImageReference();
 
            var program = @"
public class Program
{
    public static void Main()
    {
        Client.M();
    }
}
";
            var compilation = CreateCompilationWithMscorlib46(program, references: new[] { lib1Image, clientImage }, options: TestOptions.ReleaseExe);
            CompileAndVerify(compilation, expectedOutput: @"Base1");
        }
    }
}