[英]Cast an object to a class with generics
我有一個類B
的實例,它是抽象類A<TInput, TOutput>
的特殊化。 B
類有多種變體,因為我已經用各種輸入和輸出實現了它。
TInput
和TOutput
限於特定的輸入和輸出類,我們稱它們為I
和O
我正在使用Activator.CreateInstance實例化B
,但是由於它返回一個對象,因此我需要將其強制轉換為A<I, O>
。 我期望這可以工作,因為I
和O
是基類(在這種情況下, B<SpecialisationOfI, SpecalisationOfO>
)。
這是失敗的地方,因為此強制轉換顯然無效。
偽代碼:
abstract class I { }
abstract class O { }
abstract class A<TInput, TOutput>
where TInput : I
where TOutput : O
{
abstract TOutput Foo(TInput bar);
}
class Input : I { }
class Output : O { }
class B : A<Input, Output> { }
A<I, O> instance = (A<I, O>)Activator.CreateInstance(typeOfB); // <-- fail
instance.Foo(input);
有可能使這項工作嗎? 謝謝!
對我給出的答案基於編輯我已經通過重組顯著基於協方差的代碼解決了這個:我搬到Foo
從A
到一個界面:
interface IA<TResult> {
TResult Foo(object input);
}
class A<TInput, TOutput> : IA<TOutput>
where TInput : I
where TOutput : O {
public TOutput Foo(object input) {
if (!(input is TInput)) {
throw new ArgumentException("input");
}
return FooImpl(input as TInput);
}
protected abstract TOutput FooImpl(TInput input);
}
var instance = (IA<Output>) Activator.CreateInstance(type);
instance.Foo(input);
感謝您與我分享您的見解!
這與創建實例的方式無關-這是通用方差的問題。 您本質上想做的就是與此類似:
List<object> objects = new List<string>();
無效的原因是(通常)下一行代碼可能是:
objects.Add(new object());
如果試圖將其添加到確實是List<string>
類型的List<string>
,那就不好了。
現在,如果您從抽象類更改為接口,並且使用的是C#4,則可以使用通用協方差和通用逆差 :
interface class A<in TInput, out TOutput>
where TInput : I
where TOutput : O
{
abstract TOutput Foo(TInput bar);
}
這仍然不會為您的代碼的工作,雖然,因為你正在嘗試使用輸入和輸出協變。 您的B
類將具有以下方法:
Output Foo(Input bar);
...換句話說,它需要Input類型的Input
。 但是,如果您有一個A<I, O>
應該可以用於I
任何實現:
A<I, O> x = new B(); // Invalid, as discussed, to prevent...
O output = x.Foo(new SomeOtherI()); // ... this line
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.