webentwicklung-frage-antwort-db.com.de

Erzwingen Sie Unterklassen einer Schnittstelle, um ToString zu implementieren

Angenommen, ich habe eine Schnittstelle IFoo und ich möchte, dass alle Unterklassen von IFoo die ToString-Methode von Object überschreiben. Ist das möglich? 

Das Hinzufügen der Methodensignatur zu IFoo als solches funktioniert nicht:

interface IFoo
{
    String ToString();
}

da alle Unterklassen Object erweitern und auf diese Weise eine Implementierung bereitstellen, kann sich der Compiler nicht darüber beklagen. Irgendwelche Vorschläge?

52
rjohnston

Ich glaube nicht, dass Sie es mit einer Schnittstelle schaffen können. Sie können jedoch eine abstrakte Basisklasse verwenden:

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

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

Jon & Andrew: Dieser abstrakte Trick ist wirklich nützlich. Ich hatte keine Ahnung, Sie könnten die Kette beenden, indem Sie sie als abstrakt deklarieren. Prost :)

In der Vergangenheit, wenn ich ToString () in abgeleiteten Klassen überschreiben wollte, habe ich immer ein Muster wie das folgende verwendet:

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

    public override string ToString()
    {
        return ToStringImpl();
    }    
}
8
Mark Simpson

Ich weiß, dass dies Ihre Frage nicht beantwortet, aber da es keine Möglichkeit gibt, das zu tun, wonach Sie verlangen, dachte ich, ich würde meinen eigenen Ansatz teilen, damit andere ihn sehen können.

Ich verwende eine Mischung aus den vorgeschlagenen Lösungen von Mark und Andrew.

In meiner Anwendung leiten sich alle Domain-Entitäten von einer abstrakten Basisklasse ab:

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

Die Schnittstelle selbst definiert nur einen einfachen Accessor:

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

Nun ist also ein Rückfallmechanismus eingebaut - oder mit anderen Worten, eine Entity, die IHasDescription implementiert, muss die EntityDescription bereitstellen, aber jede Entity kann immer noch in eine Zeichenfolge konvertiert werden.

Ich weiß, dass sich dies nicht grundlegend von den anderen hier vorgeschlagenen Lösungen unterscheidet, aber ich mag die Idee, die Verantwortung des Basistyps Entity zu minimieren, so dass die Implementierung der Beschreibungsschnittstelle optional bleibt, aber Sie müssen die Beschreibung tatsächlich implementieren -Methode, wenn Sie die Schnittstelle implementieren.

IMHO, Schnittstellen, die von der object-Basisklasse implementiert werden, sollten nicht als implementiert "zählen" - es wäre schön, wenn Sie eine Compiler-Option dafür hätten, aber na ja ...

1
mindplay.dk

Durch die Implementierung einer Schnittstellenmethode wird die Methode implizit versiegelt (und außer Kraft gesetzt). Wenn Sie es nicht anders sagen, beendet die erste Implementierung einer Schnittstelle die Überschreibungskette in C #.

Essential .NET

Abstrakte Klasse = dein Freund

Check diese Frage

1
Ric Tokyo

Tut mir leid, diesen alten Faden aus dem Grabe ausgraben zu müssen, besonders als unser lieber @ jon-skeet bereits seine eigene Antwort lieferte .

Wenn Sie jedoch die Schnittstelle beibehalten und keine abstrakte Klasse verwenden möchten, ist dies wahrscheinlich immer noch möglich, wenn Sie einfach die Schnittstelle System.IFormattable verwenden.

interface IFoo : IFormattable
{
}

Das einzige, was zu beachten ist, um diese IFormattable richtig zu implementieren, sollte die konkrete Implementierung auch die Object.ToString() überschreiben.

Dies wird in diesem Beitrag von Nizza klar erklärt.

Ihre konkrete Klasse ist jetzt wie

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

Hoffe, das könnte noch jemandem helfen.

0
Seb T.

Ich glaube nicht, dass Sie eine beliebige Unterklasse zu override einer der virtuellen Methoden der Basisklasse zwingen können, es sei denn, diese Methoden sind abstrakt. 

0