[英]How to call a method with a generic constraint using a type parameter without the constraint?
假設我有一個方法:
public void ExampleMethod<T>(T x) where T : struct // or new()
{
// example usage, similar to what's actually happening
var z = (T)Enum.Parse(typeof(T), privateFieldOfTypeString);
// do something depending on values of x and z
// possibly using other methods that require them being enums
// or in case of the new() constraint:
// var t = new T() and do something together with x
}
我想用它如下:
public void CallerMethod<S>(S y)
{
if (typeof(S).IsEnum) // or some other invariant meaning that `S` is "new()able"
{
ExampleMethod(y); // won't compile
}
}
因此,在運行期間我知道S
滿足ExampleMethod<T>
的約束。 我知道可以使用反射調用它,類似於:
this
.GetType()
.GetMethod(nameof(ExampleMethod<object>))
.MakeGenericMethod(typeof(S))
.Invoke(this, new object[] { y });
沒有反思可能嗎?
注意:這是來自現實生活示例的簡化代碼,顯然我無法控制這些方法的簽名,因此答案“將約束添加到CallerMethod
”和“從ExampleMethod
刪除約束”無效。
是的,整個事情應該重新設計,所以整個問題根本不會出現。 但正如在現實生活中一樣,“整個事情”太大,太耦合,風險太大而無法重寫。 一些要求以一種意想不到的方式發生了變化 - 因此明顯的代碼氣味,我試圖通過將其隱藏在一個看起來很討厭的地方來最小化。
你可以使用dynamic
:
if (typeof(S).IsEnum)
{
ExampleMethod((dynamic)y);
}
您可以利用運算符重載; 定義CallerMethod
多個顯式版本, CallerMethod
版本都可以成功地對ExampleMethod
進行后續調用
CallerMethod(Enum1 value) { ExampleMethod(value); }
CallerMethod(Enum2 value) { ExampleMethod(value); }
CallerMethod(Enum3 value) { ExampleMethod(value); }
等等
如果有大量的成長型需要一個版本的CallerMethod
你可以寫一個T4模板來生成partial
與所有的實現類。
如果枚舉類型是已知的,一種可能性,雖然詳細,但將轉換為已知類型。
例如,作為一個起點,
public void CallerMethod<S>(S y) {
if (typeof(S).IsEnum) {
if (y is KnownEnum) {
var z = (KnownEnum)Enum.Parse(typeof(S), y.ToString());
ExampleMethod(z);
}
if (y is KnownEnum2) {
var z = (KnownEnum2)Enum.Parse(typeof(S), y.ToString());
ExampleMethod(z);
}
//...
}
}
在您的特定情況下,您可以轉換為int。
public void CallerMethod<S>(S y)
{
if (typeof(S).IsEnum)
{
ExampleMethod((int)y);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.