Lösung für überladene Operatoreinschränkungen in .NET-Generics

Was würde ich tun, wenn ich eine generische Methode haben möchte, die nur Typen akzeptiert, die einen Operator überladen haben, zum Beispiel den Subtraktionsoperator. Ich habe versucht, eine Schnittstelle als Einschränkung zu verwenden, aber Interfaces können nicht überladen werden.

Was ist der beste Weg, dies zu erreichen?

   

Es gibt keine unmittelbare Antwort; Operatoren sind statisch und können nicht in Zwangsbedingungen ausgedrückt werden – und die vorhandenen Primitiven implementieren keine spezifische Schnittstelle (Kontrast zu IComparable [], der verwendet werden kann, um größer als / kleiner als zu emulieren).

Jedoch; Wenn Sie nur wollen, dass es funktioniert, dann gibt es in .NET 3.5 einige Optionen …

Ich habe hier eine Bibliothek zusammengestellt , die einen effizienten und einfachen Zugang zu Generikaherstellern ermöglicht – zum Beispiel:

T result = Operator.Add(first, second); // implicit ; here 

Es kann als Teil von MiscUtil heruntergeladen werden

In C # 4.0 wird dies zusätzlich über dynamic möglich:

 static T Add(T x, T y) { dynamic dx = x, dy = y; return dx + dy; } 

Ich hatte auch (an einem Punkt) eine .NET 2.0 Version, aber das ist weniger getestet. Die andere Option besteht darin, eine Schnittstelle wie z

 interface ICalc { T Add(T,T)() T Subtract(T,T)() } 

usw., aber dann müssen Sie ein ICalc; durch alle Methoden, die unordentlich werden.

Ich habe herausgefunden, dass IL das wirklich gut bewältigen kann. Ex.

 ldarg.0 ldarg.1 add ret 

In einer generischen Methode kompiliert, wird der Code ordnungsgemäß ausgeführt, solange ein primitiver Typ angegeben wird. Es kann möglich sein, dies auf Aufrufoperatorfunktionen auf nicht-primitiven Typen auszudehnen.

Siehe hier .

Es gibt ein Stück Code, der den Internaten gestohlen wurde, für den ich viel benutze. Es sucht nach oder erstellt mit IL Grundrechenarten. Alles geschieht in einer generischen class von Operation , und Sie müssen lediglich die erforderliche Operation einem Delegaten zuweisen. Wie add = Operation.Add .

Es wird so benutzt:

 public struct MyPoint { public readonly double x, y; public MyPoint(double x, double y) { this.x=x; this.y=y; } // User types must have defined operators public static MyPoint operator+(MyPoint a, MyPoint b) { return new MyPoint(a.x+bx, a.y+by); } } class Program { // Sample generic method using Operation public static T DoubleIt(T a) { Func add=Operation.Add; return add(a, a); } // Example of using generic math static void Main(string[] args) { var x=DoubleIt(1); //add integers, x=2 var y=DoubleIt(Math.PI); //add doubles, y=6.2831853071795862 MyPoint P=new MyPoint(x, y); var Q=DoubleIt(P); //add user types, Q=(4.0,12.566370614359172) var s=DoubleIt("ABC"); //concatenate strings, s="ABCABC" } } 

Operation Quellcode mit freundlicher Genehmigung von Paste Bin: http://pastebin.com/nuqdeY8z

mit Attribution unten:

 /* Copyright (C) 2007 The Trustees of Indiana University * * Use, modification and distribution is subject to the Boost Software * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * Authors: Douglas Gregor * Andrew Lumsdaine * * Url: http://www.osl.iu.edu/research/mpi.net/svn/ * * This file provides the "Operations" class, which contains common * reduction operations such as addition and multiplication for any * type. * * This code was heavily influenced by Keith Farmer's * Operator Overloading with Generics * at http://www.codeproject.com/csharp/genericoperators.asp * * All MPI related code removed by ja72. */