我打算詢問泛型操作符+重載,但不是在典型的「我可以操作符+泛型類型」方式。C#泛型操作符 - RTTI方法
問題是在底部
最近,我開始在C#創建矩陣類,並經過一段時間它來找我,我不能做簡單的T + T!
因此,我使用Google搜索並找到了幾種解決方法。
- 創建表達link
- 創建抽象類
abstract class Matrix<T>{//some code}
。創建「受保護的虛擬方法Add(T itemToAdd)」,然後創建 操作是這樣的:T operator+(T item1, T item2){return item1.Add(item2);}
(堆棧的大部分信息),然後繼承這個方法class Matrix : Matrix<int>
here - 使用方法添加如:
T Add(T first, T second){ dynamic output = first + second; return output;}
(堆棧某處)
首先一個就是不適合我,所以我想第二個,但後來我跑進嚴重的問題,如:
- 但卻難免重複碼(的很多) - 我創造了4類:INT,雙,長,複雜 - 我自己的類型
- 創建多個擴展方法等。
第三個是如此不安全,我拒絕它immidietlay。
在我掙扎之後,我意識到:'爲什麼我不使用RTTI和反射?我知道,它在運行時很昂貴,但爲什麼不使用靜態構造函數來執行此操作?
這裏是我的想法(僞):
class Matrix<T>{
static Func<T,T,T> Add;
static Matrix
{
if(T is int)
Add = (first,second) = > ((int)first)+((int)second);
else if(T is long)
Add = (first,second) = > ((long)first)+((long)second);
// and so on for built-in types
else
{ // T is not built-in type
if(typeof(T).GetMethods().Contains("op_Addition"))
{
Add = (first,second) => typeof(T).getMethod("op_Addition").invoke(first,second);
}
}
}
我知道反思是昂貴的,但它會做的只有一次(每類)! 你開始爭論前:我要編寫T is int
這樣的:
var type = typeof(T);
if(type==typeof(int)) // code
我知道,我不能明確地轉換噸至詮釋,但必須有某種形式的「解決」。問題在於(例如)Int32沒有明確的'操作符'方法,因此反射並沒有多大用處。
所有的介紹後我有兩個問題:
- 它是一個很好的方法還是你看到它大的紕漏?
- 它可行嗎?我不想在不知道我的lambda函數是否可以工作的情況下開始創建代碼。
編輯1 + 2 我改變了我的代碼一般。 我想,也許你需要我的類的用法,在這裏你是:
Matrix<int> matrix = new Matrix(1,1); // creates int-based matrix
Matrix<MyClass> matrix2 = new Matrix(1,1); // creates some other type matrix
ANSWER基於dasblinkenlight的答案 我成功地做到這一點:
public interface ITypeTratis<T>
{
T Add(T a, T b);
T Mul(T a, T b);
T Sub(T a, T b);
T Div(T a, T b);
bool Eq(T a, T b);
}
public class IntTypeTratis : ITypeTratis<int>
{
//code for int
}
public class DoubleTypeTratis : ITypeTratis<double>
{
//code for double
}
internal class TypeTraits<T> : ITypeTratis<T>
{
public Func<T, T, T> AddF;
public Func<T, T, T> MulF;
public Func<T, T, T> DivF;
public Func<T, T, T> SubF;
public Func<T, T, bool> EqF;
public T Add(T a, T b) => AddF(a, b);
public bool Eq(T a, T b) => EqF(a, b);
public T Mul(T a, T b) => MulF(a, b);
public T Sub(T a, T b) => SubF(a, b);
public T Div(T a, T b) => DivF(a, b);
}
public class Matrix<T>
{
private static IDictionary<Type, object> traitByType = new Dictionary<Type, object>()
{
{typeof (int), new IntTypeTratis()},
{typeof (double), new DoubleTypeTratis()}
};
static Matrix()
{
Debug.WriteLine("Robie konstruktor dla " + typeof(T));
var type = typeof(T);
if (!traitByType.ContainsKey(type))
{
MethodInfo add, sub, mul, div, eq;
if ((add = type.GetMethod("op_Addition")) == null)
throw new NotSupportedException("Addition is not implemented");
if ((sub = type.GetMethod("op_Subtraction")) == null)
throw new NotSupportedException("Substraction is not implemented");
if ((mul = type.GetMethod("op_Multiply")) == null)
throw new NotSupportedException("Multiply is not implemented");
if ((div = type.GetMethod("op_Division")) == null)
throw new NotSupportedException("Division is not implemented");
if ((eq = type.GetMethod("op_Equality")) == null)
throw new NotSupportedException("Equality is not implemented");
var obj = new TypeTraits<T>
{
AddF = (a, b) => (T)add.Invoke(null, new object[] { a, b }),
SubF = (a, b) => (T)sub.Invoke(null, new object[] { a, b }),
MulF = (a, b) => (T)mul.Invoke(null, new object[] { a, b }),
DivF = (a, b) => (T)div.Invoke(null, new object[] { a, b }),
EqF = (a, b) => (bool)eq.Invoke(null, new object[] { a, b })
};
traitByType[type] = obj;
}
}
}
而這正是我在尋找。
如果有任何不清楚的地方,請隨時提出任何問題。這不是某種家庭作業 - 只要我用C#開心,但我真的想創造出好的代碼。 – MaLiN2223
你是在做這個練習嗎?或者你只是需要數學矩陣運算來做其他事情? –
在我看來,你可以從某個庫中獲得這種功能 –