12 Stimmen

Definieren Sie eine Generik, die den Operator + implementiert

Mögliches Duplikat:
Lösung für überladene Operator-Beschränkung in .NET Generika

Ich habe ein Problem, an dem ich gerade arbeite, und zwar für int s, aber ich möchte, dass es für alle Klassen funktioniert, die mit der Option + Betreiber. Gibt es eine Möglichkeit, dies im generischen Text zu definieren? Zum Beispiel,

public List<T> Foo<T>() where T : ISummable

Gibt es eine Möglichkeit, dies zu tun?

EDIT :
Leistung der Übergabe in einem Delegaten, um die Summierung zu tun, anstatt mit += mit einem Typ von Int war 540% langsamer bestenfalls. Untersuchung der möglichen anderen Lösung

Endgültige Lösung:
Ich danke Ihnen allen für Ihre Vorschläge. Ich habe eine Lösung gefunden, die nicht zu langsam ist und die Überprüfung zur Kompilierzeit durchsetzt. Ich kann nicht den ganzen Ruhm für mich beanspruchen, da mir ein Kollege dabei geholfen hat, diese Lösung zu finden. Wie auch immer, hier ist sie:

Implementierung einer Schnittstelle mit allen erforderlichen Operatoren in Form von Funktionen

public interface IFoo<InputType, OutputType>
{
    //Adds A to B and returns a value of type OutputType
    OutputType Add(InputType a, InputType b);
    //Subtracts A from B and returns a value of type OutputType
    OutputType Subtract(InputType a, InputType b);
}

Erstellen Sie die Klasse, die Sie definieren möchten, aber verwenden Sie anstelle der Where-Klausel eine Instanz der IFoo-Schnittstelle, die in die Abhängigkeit injiziert wird. Der OutputType wird meistens double sein, da die Art der Operationen mathematisch ist.

public class Bar<T>
{
    private readonly IFoo<T,double> _operators;

    public Bar(IFoo<T, double> operators)
    {
        _operators = operators;
    }
}

Wenn Sie nun diese Klasse verwenden, definieren Sie die Regeln für den Betrieb wie folgt:

private class Foo : IFoo<int, double>
{
    public double Add(int a, int b)
    {
        return (double)(a+b);
    }
    public double Subtract(int a, int b)
    {
        return (double)(a-b);
    }
}

dann würden Sie es so verwenden:

Foo inttoDoubleOperations = new Foo();
Bar myClass = new Bar(Foo);

auf diese Weise werden alle Operationen zur Kompilierzeit erzwungen :)

Viel Spaß!

10voto

Timwi Punkte 62977

Dies ist eine ziemlich häufig geforderte neue Funktion für C#: die Möglichkeit, allgemeinere Parameterbeschränkungen als die bereits vorhandenen anzugeben. Operatoren gehören zu den am häufigsten geforderten. Allerdings unterstützt C# dies derzeit nicht.

Mögliche Abhilfemaßnahmen:

  • Übergeben Sie einen Delegaten an jede Methode, die eine Addition durchführen muss. Dies ist die typsicherste Option, aber natürlich ist es ärgerlich, wenn Sie eine solche Methode häufig aufrufen müssen. Zum Beispiel:

    public class Generic<T> {
        public void DoSomething(T anItem, T anotherItem, Func<T, T, T> add) {
            // instead of
            Blah(anItem + anotherItem);
            // have to write:
            Blah(add(anItem, anotherItem));
        }
    }
    
    Generic<int> genInt = ...;
    // and then instead of ...
    genInt.DoSomething(1, 2);
    // have to write:
    genInt.DoSomething(1, 2, (a, b) => a + b);
  • Deklarieren Sie Ihre eigene Schnittstelle IAddable . Dann können Sie es als generische Typ-Parameter-Beschränkung verwenden, aber natürlich können Sie nicht int als Parameter zu verwenden. Sie müssten eine struct die nur ein int und die Folgendes implementiert IAddable :

    public interface IAddable<T> {
        T Add(T other);
    }
     
    public struct Integer : IAddable<Integer> {
        public int Value;
        public Integer(int value) { Value = value; }
        public Integer Add(Integer other) { return new Integer(Value + other.Value); }
    }
    
    // then instead of
    Generic<int> blah = ...;
    // have to write:
    Generic<Integer> blah = ...;
  • dynamic . Eine weitere mögliche Abhilfe ist die Verwendung von dynamic aber das ist ziemlich hakelig und völlig unsicher: Sie können damit jeden Typ übergeben und jede Methode oder jeden Operator aufrufen und nur zur Laufzeit abstürzen, nicht zur Kompilierzeit.

3voto

Bart Punkte 2069

In C# 4.0 ist das neue Schlüsselwort dynamisch die es Ihnen ermöglichen, dies zur Laufzeit zu tun. In früheren Versionen war es möglich, aber für mich zu fragwürdig und kompliziert. Aber man kann immer einen Delegaten übergeben, der die Additionen innerhalb von generic durchführt. Andernfalls ist es nicht möglich, da es kein ISummable, IAdditive und generell keine Möglichkeit gibt, zur Kompilierungszeit zu wissen, ob etwas additiv* ist. Wenn Sie weitere Kommentare wünschen, werde ich sie später hinzufügen. BR.

  • Ich meine, außer für die Herstellung Sie eigene IAdditive und markieren einige Typen mit ihnen, aber es wird nicht funktionieren, zum Beispiel mit ints.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X