2010-09-28 13 views
18

Ich muss eine Schnittstelle definieren, die bestimmte Überlastung des Operators auf die Typen erzwingen muss, die sie implementieren. Es scheint keinen offensichtlichen Weg dafür zu geben, da das Überladen von Operatoren mit statischen Methoden in der Klasse durchgeführt werden muss. Gibt es eine Möglichkeit, den gleichen Effekt zu erzielen (mit abstrakten Klassen oder irgendetwas anderem)?Gibt es in C# eine Möglichkeit, das Überladen von Operatoren in abgeleiteten Klassen zu erzwingen?

Antwort

23

bisschen wie ein Hack, aber ...

Sie könnten Betreiber Überlastungen in Ihrer Basisklasse zur Verfügung stellen, die dann einige der Klassen in einer abstrakten Methoden veröffentlicht nennen es die Arbeit zu erledigen.

public abstract class MyClass 
{ 
    public static MyClass operator +(MyClass c1, MyClass c2) 
    { 
     return c1.__DoAddition(c2); 
    } 

    protected abstract MyClass __DoAddition(MyClass c2); 
} 
+1

'geschützter abstrakter' anstelle 'privater abstrakter', ich denke. – abatishchev

+1

Nicht nett, aber wirkungsvoll. Ich mache es auch so. – elsni

+0

@abatishchev: whoops, danke :) – Codesleuth

8

Nein. Der einzig sinnvolle Weg wäre, eine Unit-Test-Prüfung zu verwenden, um alle konkreten Implementierungen zu finden und diese Bedingung zu überprüfen. Sie könnten auch vielleicht etwas zur Laufzeit re dasselbe über einen statischen Konstruktor, aber dann ist die Frage welche statischen Konstruktor?

Ein anderer Ansatz besteht darin, die Operatoren zu löschen und einen interface-basierten Ansatz zu verwenden; Wenn Sie zum Beispiel T benötigen, um +(T,T) zu haben, haben Sie anstelle von Operatoren eine Schnittstelle mit einer Add(T) Methode. Ein weiterer Vorteil ist, dass Schnittstellen aus Generika (typischerweise über Constraints) nutzbar sind, wobei die Verwendung von Operatoren aus generischem Code etwas Aufwand erfordert.

+1

Mit Methoden wie addieren, subtrahieren nächste offensichtliche Wahl ist, aber da mein Code wird viele Berechnungen haben wie 's = s1 * 2 + s2 * s3 - s4 * (s5 - s6);'. Durch die Verwendung von Methoden wird es "s = s1.Multiply (2) .Add (s2.Multiply (s3)). Subtrahieren (s4.Multiply (s5.Subtract (s6)));' Sicher nicht sehr lesbar! – Hemant

+0

@Hemant: Sie können Apostroph 'verwenden, um Code in Kommentare zu markieren – abatishchev

+0

@abatishchev behoben, dass; p –

5

Sie könnten das Überladen in einer abstrakten Basisklasse implementieren, aber die tatsächlichen Vorgangsmerkmale an eine abstrakte Methode delegieren. Dann muss dies implementiert werden und das Überladen wird mit ihrer Implementierung verhindert.

public abstract class OverLoadingBase 
{ 
    public abstract OverLoadingBase DoAdd(OverLoadingBase y); 

    public static OverLoadingBase operator +(OverLoadingBase x, OverLoadingBase y) 
    { 
     return x.DoAdd(y); 
    }  
} 

Obwohl ich nicht sicher bin, ob das vollständig ist.

+0

@abatishchev - Ich bin neugierig - warum das Klammerformat ändern? –

1

Da sein Operator nur überlastet werden kann und nicht übersteuert ist es ziemlich schwierig. Die beste Lösung, die ich mir vorstellen kann, ist eine abstrakte Klasse zu verwenden und so zu überladen.

public abstract class MyBase 
{ 
    public abstract MyBase Add(MyBase right); 
    public abstract MyBase Subtract(MyBase right); 

    public static MyBase operator +(MyBase x, MyBase y) 
    { 
     //validation here 
     return x.Add(y); 
    } 

    public static MyBase operator -(MyBase x, MyBase y) 
    { 
     //validation here 
     return x.Subtract(y); 
    } 
} 
3

ich dies in der Vergangenheit getan haben ...

public abstract class BaseClass<TClass> where TClass : BaseClass 
{ 
    public static TClass operator +(TClass c1, TClass c2) 
    { 
     return c1.DoAddition(c2); 
    } 

    protected abstract TClass DoAddition(TClass c2); 
} 

Und dann wie folgt umgesetzt:

public class ConcreteClass : BaseClass<ConcreteClass> 
{ 
    protected ConcreteClass DoAddition(ConcreteClass c2) 
    { 
     ... 
    } 
} 
Verwandte Themen