我有一个通用基类Foo<T>
,类Bar<U>
和Bat<T>
派生自该基类。
U
源自T
。U
Bat 和 Bar 是类似的实现,只是在几个必须以不同方式处理类型值的地方有所不同。
在Foo
中,我有一个工厂方法Create
,它接受一个类型的参数T
并且应该创建一个Bar
或Bat
对象。它看起来大致是这样的:
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
不是 a 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
在这种情况下,由于继承,无论如何都不能成为结构,但我还有另一种情况,我想根据 ifT
是 astruct
或 a来调用方法class
)。
在 C++ 中,可以通过提供具有不同类型约束的方法的多个重载来解决(iirc)这样的场景Create
,编译器将检查类型T
并选择正确的方法(使用U
或T
作为类型约束)。
我不知道 C# 中有类似的内置解决方案,但也许我可以使用一种优雅的解决方法?(反思是一个明显的答案,但不是一个选项)