在C#中强制覆盖ToString()时覆盖和新的区别

时间:2014-10-22 09:52:45

标签: c# override tostring

我有这个实验代码:

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.WriteToString(params object[])之类的签名,并使用object.ToString()实现。

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

2 个答案:

答案 0 :(得分:0)

如果是Console.WriteLine(a2); Console.WriteLine方法中的a2的编译时类型是一个对象,因为调用了一个对象的重载。由于您没有重写对象的ToString()方法,因此调用对象中的默认ToString()。您没有覆盖对象上的ToString(),因为您通过“new”关键字(用于隐藏父类的方法)将方法隐藏在抽象类中来打破链。

答案 1 :(得分:0)

不是试图强迫人们覆盖ToString,而是为了不只是在你的类上有一个调用抽象方法的基本实现。例如:

abstract class Base
{
  protected abstract string GetMessage();

  public sealed override string ToString()
  {
    return GetMessage();
  }
}

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

现在你不是想欺骗编译器,任何使用你的类的人都会明白他们必须做的事情。