强制接口的子类实现 ToString

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

仅仅将方法签名添加到 IFoo 本身是不起作用的:

interface IFoo
{
String ToString();
}

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

26517 次浏览

我不相信你可以用一个接口来实现,但是你可以使用一个抽象的基类:

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


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

我不认为您可以强制任何子类到 重写任何基类的虚方法,除非这些方法是抽象的。

实现接口方法隐式地封闭该方法(以及重写它)。因此,除非您另有说法,否则接口的第一个实现将在 C # 中结束覆盖链。

必不可少的.NET

抽象类 = 你的朋友

检查 这个问题

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

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

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


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

我知道这不能回答你的问题,但是既然没有办法做到你所要求的,我想我应该分享我自己的方法给其他人看。

我使用了马克和安德鲁提出的解决方案的混合体。

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

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; }
}

所以现在有一个内置的后退机制——换句话说,实现 IHasDescriptionEntity必须提供 EntityDescription,但是任何 Entity仍然可以转换成字符串。

我知道这和这里提出的其他解决方案没有根本的不同,但是我喜欢最小化基本 Entity类型的责任的想法,这样实现 description-interface 仍然是可选的,但是如果你实现了接口,你就必须实现 description-method。

恕我直言,由 object基类实现的接口不应该像实现的那样“计数”——如果有一个编译器选项就好了,但是,哦,好吧..。

很抱歉把这条旧线从坟墓里挖出来,特别是作为我们亲爱的@jon-skeet 已经给出了他自己的答案

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

interface IFoo : IFormattable
{
}

要记住的唯一一件事是,要正确地实现这个 IFormattable,具体的实现也应该覆盖 Object.ToString()

这一点在这篇精彩的文章中得到了清楚的解释。

你的混凝土课程现在就像

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);
}
}

希望这能帮到大家。