如何使用new关键字隐藏一个方法?

6

我读过一篇关于new关键字的文章。它说它用于隐藏方法,以下是他们给出的示例:

using System;

namespace ConsoleApplication3
{
    class SampleA
    {
        public void Show()
        {
            Console.WriteLine("Sample A Test Method");
        }
    }

    class SampleB:SampleA
    {
        public void Show()
        {
            Console.WriteLine("Sample B Test Method");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            SampleA a = new SampleA();
            SampleB b = new SampleB();
            a.Show();
            b.Show();
            a = new SampleB();
            a.Show();
            Console.ReadLine();
        }
    }
}

输出:

样例 A 测试方法

样例 B 测试方法

样例 A 测试方法

所以我的问题不是 new 关键字用于实例化一个对象吗?它被用于为新创建的对象分配内存吗?那么如何使用它进行方法隐藏呢?以上示例是否正确?


你能发一个链接吗? - JDE
“new”这个关键字在C#中有几种含义,其中之一是在子类中隐藏基类方法。 - Alex
1
看看这个是否有帮助 - https://dev59.com/PV0a5IYBdhLWcg3wipNA?rq=1 - Sanket
@JDE:这是链接 http://www.aspdotnet-suresh.com/2013/09/csharp-virtual-override-new-keywords-example.html - Neelam Prajapati
@NeelamPrajapati提供的链接本身就解释了new关键字在方法隐藏中的实际作用。 - Rahul Hendawe
4个回答

8

new有三个不同的用法。你可以说它是拥有相同名称的三个不同关键字。

  1. It's an operator, used to invoke constructors. Example: new object();
  2. It's a modifier, used to hide an inherited member from a base class member. Example:

    class Base {
        public void MyMethod() {
            //Do stuff
        }
    }
    
    class Derived : Base {
        public new void MyMethod() {
            //Do other stuff
        }
    }
    
  3. It's a generic type constraint, used to indicate that a generic type parameter has a parameterless constructor. Example:

    class MyGenericClass<T> : where T : new() { ... }
    

来源:新建


我理解你想表达的意思。但是在我提出问题的示例中,派生类的show方法中没有新的关键字。那么SampleB类的对象如何调用SampleA类的show()方法呢? - Neelam Prajapati
1
@NeelamPrajapati a编译时类型SampleA,因为你声明它为SampleA a = ...。当你调用Show()时,它将调用在SampleA中声明的方法。它不会查看a运行时类型,因为该方法不是虚拟的。(第一次,运行时类型是SampleA,第二次是SampleB,但编译时类型始终为SampleA) b的编译时类型总是SampleB,因为你说了SampleB b = ... - Dennis_E
在我的情况下,隐含的 "new" 关键字确实会发出警告,建议将其明确化。为了使用派生类方法而不是强制转换为基类型,您需要使用 "override" 关键字。 - Paul Stelian
应该是这样的:public void new MyMethod() { //Do other stuff },我的意思是new应该在void之前。 - bayram
@bayram 学到了新东西。谢谢。 - Dennis_E
显示剩余3条评论

4

“new”关键字不是用于实例化对象吗?

是的,除此之外还有其他用途。

那么如何使用它进行方法隐藏呢?

在方法和属性定义的上下文中,“new”关键字具有与用于实例化对象的“new”关键字不同的含义。在这种情况下,“new”关键字表示该特定方法或属性的继承树开始了一个新的分支。仅此而已。


我会说“继承树的起点”这个词汇,但是更准确的说法是它正在重用一个标识符,不是吗? - Matías Fidemraizer
是的,但它会破坏继承树,在我看来这是误解 OP 的关键部分。 - Patrick Hofman

2
那么如何使用它进行方法隐藏?上面的例子正确吗?
编程语言的语法、语法和语义只是一组任意的约定和规范。也就是说,C#可以发明一个、两个或十几个给定关键字(如new)的用法。
当在类成员声明期间使用new时,它表示您正在重新使用标识符:
public class A
{
    public string Text { get; set; }
}

public class B : A
{
    new public int Text { get; set; }
}

正如您可以在上面的代码示例中看到的那样,B 也实现了一个 Text 属性,但是由于它派生自 A,后者也已经定义了一个 Text 属性,因此存在命名冲突。
所谓的 new 关键字可用于重用 Text 标识符,并能够实现另一个属性 Text,该属性可能与基类中实现的属性完全不同。请注意,B 上的 Textint 类型的!
最重要的一点是,重用标识符并不等同于使用多态性,其中类方法或属性覆盖必须匹配基类成员的签名:
public class A
{
    public virtual string Text { get; set; }
}

public class B : A
{
    public override string Text 
    {
         get { return base.Text; }
         set { base.Text = value; }
    }
}

此外,重复使用标识符是很危险的:

public class A
{
    public string Text { get; set; }
}

public class B : A
{
    new public int Text { get; set; }
}


B b = new B();
b.Text = 4;

// Upcast B to A
A a = b;
a.Text = "Bye bye";

Console.WriteLine(a.Text); // Output: Bye bye
Console.WriteLine(b.Text); // Output: 4

查看Text的输出。由于重用标识符不是多态,而在上述情况下两者是完全不同的属性,因此有一个可以分别设置的A.Text和B.Text。


这里最重要的一点是,重复使用标识符并不等同于使用多态性,其中类方法或属性覆盖必须匹配基类成员签名。这对我来说是理解为什么在这种情况下使用new关键字很有用的关键。谢谢。 - llanfair

1
要隐藏一个继承的成员,可以在派生类中使用相同的成员名称声明它,并使用 new 关键字进行修改。例如:
public class BaseC
{
    public static int x = 55;
    public static int y = 22;
}

public class DerivedC : BaseC
{
    // Hide field 'x'.
    new public static int x = 100;

    static void Main()
    {
        // Display the new value of x:
        Console.WriteLine(x);

        // Display the hidden value of x:
        Console.WriteLine(BaseC.x);

        // Display the unhidden member y:
        Console.WriteLine(y);
    }
}
/*
Output:
100
55
22
*/

你可以在 这里 阅读更多内容。

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