强制接口的子类来实现ToString

时间:2009-02-04 07:01:56

标签: c# oop

假设我有一个接口IFoo,我希望IFoo的所有子类都覆盖Object的ToString方法。这可能吗?

简单地将方法签名添加到IFoo不起作用:

interface IFoo
{
    String ToString();
}

因为所有子类都扩展Object并以这种方式提供实现,所以编译器不会抱怨它。有什么建议吗?

7 个答案:

答案 0 :(得分:81)

我不相信你能用界面做到这一点。您可以使用抽象基类:

public abstract class Base
{
    public abstract override string ToString(); 
}

答案 1 :(得分:21)

abstract class Foo
{
    public override abstract string ToString();
}

class Bar : Foo
{
    // need to override ToString()
}

答案 2 :(得分:8)

Jon&安德鲁:这个抽象技巧真的很有用;我不知道你可以通过宣称它是抽象的来结束链条。干杯:)

过去当我要求在派生类中覆盖ToString()时,我总是使用如下模式:

public abstract class BaseClass
{
    public abstract string ToStringImpl();

    public override string ToString()
    {
        return ToStringImpl();
    }    
}

答案 3 :(得分:1)

实现接口方法隐式密封方法(以及覆盖它)。因此,除非您另外说明,否则接口的第一个实现将终止C#中的覆盖链。

Essential .NET

抽象类=你的朋友

检查this question

答案 4 :(得分:1)

我知道这不能回答你的问题,但由于没有办法做你所要求的,我想我会分享我自己的方法让别人看。

我使用Mark和Andrew提出的解决方案的混合体。

在我的应用程序中,所有域实体都派生自抽象基类:

public abstract class Entity
{
    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    public override string ToString()
    {
        return this is IHasDescription
                   ? ((IHasDescription) this).EntityDescription
                   : base.ToString();
    }
}

界面本身只定义了一个简单的访问者:

public interface IHasDescription : IEntity
{
    /// <summary>
    /// Creates a description (in english) of the Entity.
    /// </summary>
    string EntityDescription { get; }
}

所以现在有一个内置的回退机制 - 换句话说,实现Entity的{​​{1}}必须提供IHasDescription,但任何EntityDescription仍然可以转换为字符串。

我知道这与此处提出的其他解决方案没有根本的不同,但我喜欢最小化基类Entity类型的责任的想法,因此实现description-interface仍然是可选的,但是你'如果您正在实现接口,则强制实际实现description-method。

恕我直言,由Entity基类实现的接口不应该像实现那样“计数” - 为此设置编译器选项会很好,但是,哦......好吧......

答案 5 :(得分:0)

我认为你不能强迫任何子类覆盖任何基类的虚方法,除非这些方法是抽象的。

答案 6 :(得分:0)

很抱歉从坟墓中掩埋这条旧线,特别是作为我们亲爱的@ jon-skeet already provided his own answer

但是,如果您想保留该接口而不使用抽象类,那么我猜想,仍然可以通过简单地使您的接口实现System.IFormattable接口来实现。

interface IFoo : IFormattable
{
}

唯一要记住的是,要正确实现此IFormattable,具体实现也应覆盖Object.ToString()

This is clearly explained in this nice post.

您的具体课程现在就像

public class Bar : IFoo
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        return $"{nameof(Bar)}";
    }

    public override string ToString()
    {
        return ToString(null, System.Globalization.CultureInfo.CurrentCulture);
    }
}

希望这仍然可以帮助任何人。