簡體   English   中英

如何使用沒有約束的類型參數調用具有泛型約束的方法?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM