3

在 C# 中,如果我有

public class BaseClass
{
    //BaseClass implementation
}

public class Derived : BaseClass
{
    //Derived implementation
}

public class AnotherClass
{
    AnotherClass(BaseClass baseClass)
    {
        //Some code
    }

    AnotherClass(Derived derived) : this(derived as BaseClass)
    {
        //Some more code
    }
}

然后做:

BaseClass    baseVariable    = new Derived();
AnotherClass anotherVariable = new AnotherClass(baseVariable);

这会导致提前绑定,调用AnotherClass(BaseClass)方法。

相反,如果我使用dynamic关键字转换它 - 或使用动态实例化一个变量,然后将其作为构造函数参数传递,AnotherClass(Derived)则将调用:

BaseClass    baseVariable    = new Derived();
//This will instantiate it using the AnotherClass(Derived)
AnotherClass anotherVariable = new AnotherClass(baseVariable as dynamic);

方法是否在 C# 中重载早期绑定(在编译时评估)?那个意思,有没有其他的方法或者技巧确定对另一个类构造函数的主要派生调用在不使用dynamic或反射的情况下,应用将主要派生类类型作为参数的构造函数的调用?

4

2 回答 2

11

C#中的绑定时间取决于绑定是否涉及dynamic。如您所见,如果使用,dynamic您将获得执行时重载解决方案;如果不这样做,您将获得编译时重载解决方案。

请注意,即使重载决议涉及动态类型,它仍将使用编译时已知的信息 - 只有类型的表达式dynamic使用执行时类型。例子:

using System;

class Test
{
    static void Main()
    {
        object x = "abc";
        dynamic y = 10;

        Foo(x, y); // Prints Foo(object,int)
    }

    static void Foo(object x, int y)
    {
        Console.WriteLine("Foo(object,int)");
    }

    static void Foo(string x, int y)
    {
        Console.WriteLine("Foo(string,int)");
    }
}

如果您将声明的类型更改xdynamic执行时类型将是相关的(并且它将打印Foo(string,int))。

当然,这只是重载决议 - 覆盖总是在执行时确定,除非您使用非虚拟调用(调用非虚拟方法或使用base.Foo(...).

于 2015-12-14T15:51:32.910 回答
1

关于这一点:

是否有任何其他方法或技巧来确定对其他类构造函数的主要派生调用 - 除了反射?

找出存储在引用中的对象的最派生类型的唯一方法是询问它(使用GetType或其他方式)。所以不,反思在这里是不可避免的。

如果您已经知道派生最多的类型是什么,那么您当然可以在传入之前强制转换为它,以便在编译时选择适当的重载。您也可以var在第一个代码段中使用自动使用最派生的类型作为引用。

于 2015-12-14T16:03:42.877 回答