簡體   English   中英

是否有(優雅的)解決方案在方法中進一步約束泛型類型參數?

[英]Is there an (elegant) solution to constrain a generic type argument further within a method?

我有一個通用基類Foo<T> ,它從中派生Bar<U>Bat<T> U源自T Bat和Bar是類似的實現,僅在必須以不同方式處理U型值的幾個地方有所不同。

Foo ,我有一個工廠方法Create ,它使用類型T的參數,並且應該創建BarBat對象。 大致如下所示:

public static IFoo<T> Create(T input) {
  if (input.TypeIdentifier == Types.Bar) {// exemplary type check
    // input is of or derives from `U`
    // return a Bar<U>
  } else 
    return new Bat(input);
}

// usage:
U myU = new ClassThatDerivesFromU();
T myT = new ClassThatDerivesFromT(CouldBe.Of(Type.U));
var myFoo1 = Create(myU); // of type IFoo<U>
var myFoo2 = Create(myT); // of type IFoo<T>

由於T不是U ,所以我無法實例化Bar對象。

一種可能的解決方案是:

public static U To<T, U>(T input) where U : T {
  return input as U;
}

// to create Bar:
new Bar(To<T, U>(input));

但是,這確實是一個hack imo,並且不能與結構一起使用(在這種情況下, U不能由於繼承而成為結構,但是我還有另一種情況,我想根據Tstruct還是class來調用方法例)。

在C ++中,可以通過提供具有不同類型約束的Create方法的幾個重載來解決(iirc)這樣的情況,並且編譯器將檢查類型T並選擇正確的方法(使用UT作為類型約束)。

我不知道C#中有類似的內置解決方案,但是也許可以使用一種優雅的解決方法來代替? (反思是一個明顯的答案,但不是一個選擇)

是的,使用接口時允許通用差異。 您可以在IFoo中將泛型類型參數聲明為協變或逆變的(取決於用法)。 如果希望使用派生類型更多的類型,則類型T必須是協變的,並且可以如下聲明IFoo:

interface IFoo<in T> { ... }

請訪問此MSDN頁面 ,以獲取有關C#中的泛型和變量的更多信息。

更新

如果您將IFoo<U> IFoo<T>條件是U : T (例如IFoo的通用類型是互變的),則可以自由地在create方法中強制轉換:

return (IFoo<T>)((object)new Bar<U>());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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