如何将Base对象的引用更改为Derived,它被实例化为Derived类型

时间:2014-02-07 07:53:53

标签: c# inheritance

为什么我无法从Derived访问M3方法? Intellisense仅显示基类中的M1和M2。 如何将bc的参考值从Base类型更改为Refernce Type, 这样我就可以访问M3方法。

class Program
{
    static void Main(string[] args)
    {
        Base bc = new Derived();
        bc.M3():// error
    }
}

class Base
{
    public void M1()
    {
        Console.WriteLine("M1 from BASE.");
    }
    public void M2()
    {
        Console.WriteLine("M2 from BASE.");
    }
}

class Derived : Base
{
    public void M3()
    {
        Console.WriteLine("M3 from DERIVED.");
    }
}

5 个答案:

答案 0 :(得分:6)

编译器必须在编译时解析名称M3。这是在Base类型的引用上调用的,Base没有该名称的成员。它碰巧在运行时指向Derived的实例这一事实在这里没有任何意义,因为编译器正在查看编译时可用的信息。

是的,在这种特定情况下,编译器可以看到bc始终初始化为Derived值,因此它应该在那里看。然而,这不是c#编译器的工作原理。它只查看所涉及引用的编译时类型

答案 1 :(得分:1)

因为您将您的类型转换为基类,所以所有可用成员的集合将减少为Base中可用的成员集。

Derived bc = new Derived();
bc.M3():// CORRECT

或只是

var bc = new Derived();
bc.M3():// CORRECT

如果您需要在应用中使用Base类进行多态,并且需要使用M3(),请考虑将其移至Base

答案 2 :(得分:1)

因为bc引用带来的唯一保证是它会引用Base的实例或从Base派生的内容。

考虑代码是否改变如下:

Base bc = new Derived();
if(DateTime.DayOfWeek == DayOfWeek.Sunday)
{
  bc = new Base();
}
bc.M3();

这是完全合法的,因为bc的保证仍然完整。

有两种方法可以解决这个问题:Casting和polymorphism。

转换意味着您告诉编译器您知道这确实是Derived实例,即使引用属于Base类型。

Base bc = new Derived();
if(bc is Derived)
{
  ((Derived)bc).M3();
}

另一种是在基类中声明M3函数,然后在派生类

中覆盖它
class Base
{
   // Other stuff...

   public virtual void M3()
   {
   }
}

class Derived : Base
{
    public override void M3()
    {
        Console.WriteLine("M3 from DERIVED.");
    }
}

答案 3 :(得分:1)

正如其他人所说,bc被声明为Base类型。你需要先施展它

    Base bc = new Derived();
    ((Derived)bc).M3()

如果bc实际上是Base类型而不是Derived,则会出现运行时错误。

答案 4 :(得分:1)

这是因为编译器只看到您正在使用Base类型的变量。

请使用以下代码:

Base bc = null;

if (SomeValue)
{
    bc = new Base();
}
else
{
   bc = new Derived();
}

SomeValue的值在运行时可能会有所不同。这意味着编译器在编译时不会知道bc的实际类型。这是基类的全部概念。您与基类共享相同的接口,但您可以更改方法的实现。

但是,您可以将类型转换为其他类型:

Derived dc = bc as Derived;

if ( dc != null ) // cast succeeded so we have a Derived
{
    dc.M3();
}

要仅检查某个类型是否属于其他类型,您可以使用isif (dc is Derived)

请注意这样做的危险。这样,您就会使用所有类型特定的检查来乱丢代码,这使得它更难理解和维护。如果您想了解更多有关此内容的信息,请阅读S OLID patterns