在C#中强制重写ToString()时,重写和new之间的区别

本文关键字:重写 new 之间 区别 ToString | 更新日期: 2023-09-27 18:27:28

我有这个经验代码:

interface I { string ToString(); }
class TestI : I {
    public override string ToString() { return "Hello"; } 
}
abstract class A1 { public override abstract string ToString(); }
class TestA1 : A1 {
    public override string ToString() { return "world!"; }
}
abstract class A2 { public new abstract string ToString(); }
class TestA2 : A2 {
    public override string ToString() { return "world!"; }
}
class Program {
    static void Main(string[] args) {
        TestI ti = new TestI();
        I i = ti;
        Console.WriteLine(ti); Console.WriteLine(i); //predictable writes "Hello"
        TestA1 ta1 = new TestA1();
        A1 a1 = ta1;
        Console.WriteLine(ta1); Console.WriteLine(a1); //predictable writes "world!"
        TestA2 ta2 = new TestA2();
        A2 a2 = ta2;
        Console.WriteLine(ta2); Console.WriteLine(a2); //writes "ConsoleApplication1.TestA2"
        Console.WriteLine(ta2.ToString()); Console.WriteLine(a2.ToString()); //good
        Console.ReadLine();
    }
}

为什么new关键字会破坏案例#3中的方法ToString()?我知道方法Console.Write有一个类似ToString(params object[])的签名,它使用object.ToString()实现。

在这种情况下,如何正确地强制覆盖ToString()?我不想使用案例4。

在C#中强制重写ToString()时,重写和new之间的区别

与其试图强迫人们重写ToString,为什么不在类上有一个调用抽象方法的基本实现呢。例如:

abstract class Base
{
  protected abstract string GetMessage();
  public sealed override string ToString()
  {
    return GetMessage();
  }
}
class Derived : Base
{
  protected override string GetMessage()
  {
    return "hello";
  }
}

现在你没有试图欺骗编译器,任何使用你的类的人都会清楚地知道他们必须做什么。

案例Console.WriteLine(a2);Console.WriteLine方法中a2的编译时类型是一个对象,因为调用了获取对象的重载。由于您没有重写对象的ToString()方法,因此会调用对象中的默认ToString(。您没有在对象上重写ToString(),因为您通过"new"关键字(用于隐藏父类的方法)将方法隐藏在抽象类中,从而破坏了链。