在C#中使用new关键字

8

我有两个类

class  A
{
     public virtual void Metod1()
     {
         Console.WriteLine("A.Method1");
     }
}

class B : A
{
    public new void  Metod1()
    {
        Console.WriteLine("B.Method1");
    }
}

然后我编写一些代码来声明这些类的实例,并调用它们的方法。
     static void Main(string[] args)
    {
        A a = new B();
        a.Metod1();
        B b = new B();
        b.Metod1();
        Console.ReadKey();
    }

我给出了以下结果:
A.Method1
B.Method1

但是当我从类B的方法1的签名中删除new关键字并运行Main方法时,我得到了相同的结果。 问题:方法签名中的new关键字只是为了更好的可读性吗?

编辑:有没有情况下我们不能不使用new关键字?


你必须在B类中使用override或new,否则它会隐藏父元素的方法。默认是new,所以如果你不加new,它不会报错并且可以正常运行。 - Vishal Sharma
附注:在这种情况下,“new”的主要用途是“混淆读者和代码用户”。有些情况下使用它可能会提高可读性(例如需要为某些不友好的基类派生类),但在大多数情况下,它只会使人难以理解何时调用基类方法和派生类方法。 - Alexei Levenkov
3个回答

8
新的关键字让代码读者知道这个方法会隐藏其基类中同名的方法。即使你不加它,编译器也会以相同的方式处理它,但会警告你。由于你将方法声明为虚拟的,在编译时会得到以下警告:
'B.Metod1()' 隐藏了继承的成员 'A.Metod1()'. 要使当前成员重写该实现,请添加 override 关键字。否则添加 new 关键字。
然而,如果您通过删除 "虚拟" 的声明来更改声明:
  • Declaration without virtual in A

    class A {
        public void Metod1() {
            Console.WriteLine("A.Method1");
        }
    }
    
    class B: A {
        public void Metod1() {
            Console.WriteLine("B.Method1");
        }
    }
    

仍然可以编译,但是警告信息将会是:

'B.Metod1()' 隐藏了继承的成员 'A.Metod1()'。如果此举是有意的,请使用 new 关键字。

与上述任何方式一样,以下内容也适用:

  • Test code

    var b=new B();
    b.Metod1();
    (b as A).Metod1();
    

将输出:

B.Method1
A.Method1

但是,如果你将其声明如下:

  • Declaration with override in B

    class A {
        public virtual void Metod1() {
            Console.WriteLine("A.Method1");
        }
    }
    
    class B: A {
        public override void Metod1() {
            Console.WriteLine("B.Method1");
        }
    }
    
然后输出将会是:
B.Method1
B.Method1
这是因为基础类的Method1不仅被隐藏,而且被派生类覆盖了。
如果Method1是抽象类中的抽象方法,那么你不能仅使用new
  • Code that must use override in derived classes

    abstract class A {
        public abstract void Metod1();
    }
    
    class B: A {
        public override void Metod1() { // use `new` instead of `override` would not compile
            Console.WriteLine("B.Method1");
        }
    }
    
在这种情况下,你不能简单地使用new,因为A要求派生类覆盖Method1

没问题,但是问题是:方法签名中的new关键字仅用于更好的可读性吗?还有哪些情况下我们不能不使用new关键字呢? - vborutenko
所以它实际上并不改变任何行为——只是为了可读性而已? - Don Cheadle

6

使用Override和New关键字的时机(C#编程指南)

在C#中,派生类中的方法可以与基类中的方法同名。您可以使用new和override关键字来指定这些方法之间的交互方式。override修饰符扩展了基类方法,而new修饰符则隐藏了它。

另外

通过使用new,您断言自己知道它修改的成员隐藏了从基类继承的成员。


基类中的方法是否仍需要virtual,才能让派生类的new有任何影响?在我的测试中,派生类上有new与没有override相同 - 我漏掉了什么?什么是“hides it”的意思? - Don Cheadle

3

你写的是为了在这种情况下更好地阅读。但是有没有情况下我们不能不使用一个新的关键字? - vborutenko
@cosset 是的,当它不用作修饰符时,例如:Class1 C = new Class1() 或者当你设置将警告视为错误时。 - G.Y
在方法、字段的签名中,是否存在不能不使用新关键字的情况? - vborutenko
@cosset 新关键字可以在泛型声明中作为运算符、修饰符和约束使用。只有当它作为修饰符使用时,才能省略它,但这会导致警告。在其他情况下,如果不使用它,则会改变代码行为,因此不能省略。 - G.Y

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接