C# 从基类调用子类的新方法

C# 从基类调用子类的新方法,c#,methods,new-operator,invoke,base-class,C#,Methods,New Operator,Invoke,Base Class,我上过这样的课 namespace ConsoleApplication1 { class Program { static void Main(string[] args) { A a = new C(); a.method(); Console.ReadLine(); } } public class A { pu

我上过这样的课

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public override void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}
它工作正常,打印“C中的方法”

但是

如果我遇到这样的情况

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public virtual void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public override void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            A a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}

它会打印“来自A的方法”。如果不采用带覆盖的cast或change方法声明,如何获得第一个示例的相同行为?

您不能-这种行为上的差异是使用virtual/override的关键

当您用“new”声明一个方法时,您的意思是“我知道我隐藏了一个具有相同签名的方法,而不是覆盖它;我不想要多态行为。”

同样,当您声明一个方法而不指定“virtual”时,您的意思是“我不希望子类能够重写这个方法。”

你为什么要这样做?您实际上只是试图重写一个尚未声明为虚拟的方法吗?如果是这样的话,那就没有办法了——这是有充分理由的。如果作者在设计类时没有考虑多态性,那么如果您能够重写该方法,它可能很容易崩溃

当然,如果您将变量声明为子类的类型,如下所示:

C c = new C();
c.method();

然后,这将调用新声明的方法。

就像Jon说的那样,避免使用它。但是

static void Main(string[] args)
    {
        A a = new C();

        (a as C).method();

        Console.ReadLine();
    }

您可以使用动态关键字调用此方法

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic a = new C();

            a.method();
            Console.ReadLine();
        }
    }

    public class A
    {
        public void method()
        {
            Console.WriteLine("METHOD FROM A");
        }
    }

    public class B : A { }

    public class C : B
    {
        public new void method()
        {
            Console.WriteLine("METHOD FROM C");
        }
    }
}