.NETジェネリックのオーバーロード演算子制約のソリューション
-
02-07-2019 - |
質問
演算子、たとえば減算演算子をオーバーロードした型のみを受け入れる汎用メソッドが必要な場合はどうしますか。インターフェイスを制約として使用しようとしましたが、インターフェイスに演算子のオーバーロードを設定できません。
これを達成する最良の方法は何ですか?
解決
即時の回答はありません。演算子は静的であり、制約で表現することはできません-既存のプリミティブは特定のインターフェイスを実装していません(IComparable [<!> lt; T <!> gt;]とは対照的です。 -than)。
ただし;単に動作させたい場合は、.NET 3.5にいくつかのオプションがあります...
ライブラリこちらを作成して、効率的に次のようなジェネリックを持つ演算子への簡単なアクセス:
T result = Operator.Add(first, second); // implicit <T>; here
の一部としてダウンロードできます。
さらに、C#4.0では、これはdynamic
:
static T Add<T>(T x, T y) {
dynamic dx = x, dy = y;
return dx + dy;
}
.NET 2.0バージョンも(ある時点で)持っていましたが、テストはあまり行われていません。もう1つのオプションは、
などのインターフェースを作成することですinterface ICalc<T>
{
T Add(T,T)()
T Subtract(T,T)()
}
etc、しかしその後、すべてのメソッドにICalc<T>;
を渡す必要があり、面倒になります。
他のヒント
ILが実際にこれをうまく処理できることがわかりました。例
ldarg.0
ldarg.1
add
ret
汎用メソッドでコンパイルされたコードは、プリミティブ型が指定されている限り正常に実行されます。これを拡張して、非プリミティブ型の演算子関数を呼び出すことができます。
こちらを参照してください。
インターネットから盗まれたコードがありますが、これは私がよく使用しています。 IL
基本的な算術演算子を使用して検索またはビルドします。それはすべてOperation<T>
ジェネリッククラス内で行われ、必要な操作はデリゲートに割り当てるだけです。 add = Operation<double>.Add
のように。
次のように使用されます:
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+b.x, a.y+b.y);
}
}
class Program
{
// Sample generic method using Operation<T>
public static T DoubleIt<T>(T a)
{
Func<T, T, T> add=Operation<T>.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"
}
}
<=>ソースコードの貼り付けビンの提供: http://pastebin.com/nuqdeY8z
以下の帰属あり:
/* 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.
*/