[英]How to upcast generic type parameters
在這種情況下,當我使用反射時,創建的類型可以是許多泛型類型。
BaseStepHandler<BaseStepDataModel> activator = (BaseStepHandler<BaseStepDataModel>)Activator.CreateInstance(....);
創建的實例可以是BaseStepDataModel的所有子級。
BaseStepHandler<OneDataModel>
OR
BaseStepHandler<TwoDataModel>
OneDataModel和TwoDataModel擴展了BaseStepDataModel。
這是我得到的例外:
無法將類型為..GlobalOnBoardingStepOneHandler的對象轉換為類型為..BaseStepHandler`1 [.... BaseStepDataModel]的對象。
這是GlobalOnBoardingStepOneHandler的聲明。
public class GlobalOnBoardingStepOneHandler : BaseStepHandler<GlobalOnBoardingStepOneDataModel>{}
您正在獲取異常,因為GlobalOnBoardingStepOneHandler
繼承自BaseStepHandler<GlobalOnBoardingStepOneDataModel>
,而不是BaseStepHandler<BaseStepDataModel>
。 這可能是.NET泛型最常見的錯誤。 類型參數的泛型不是協變的。
看到:
http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
等等...
問題是您假設因為GlobalOnBoardingStepOneDataModel
繼承自BaseStepDataModel
,所以GlobalOnBoardingStepOneHandler
繼承了BaseStepHandler<BaseStepDataModel>
。 事實並非如此,因此您不能從一個投射到另一個。
例如,請考慮以下內容:
var myListOfStrings = new List<String>();
// By your logic, this should compile (it doesn't):
var myListOfObjects = ((List<Object>)myListOfStrings);
// But if it did, this would be possible:
myListOfObjects.Add(1); // Holy cow, I just added an integer to a list of strings! What is the world coming to?
現在,這對於恢復Java程序員非常困惑,因為這在Java中是可能的 。 在Java中,您具有類型擦除,因此在運行時List<String>
實際上只是List<Object>
,因此您可以將其強制轉換為所需的任何內容,然后將所需的內容放入其中。 因為CLR使用的是通用化的泛型,而不是類型擦除,所以List<String>
實際上是與List<Object>
或List<Integer>
分離的獨立類型。
這里的問題是你希望
逆變
協方差具體類型泛型參數。
基本上,您永遠不會使用具體的類型實現目標,但是有一種解決方法。
您可以設計一個標記界面,如下所示:
public interface IBaseStepHandler<out T> // "out" marks T as covariant
where T : BaseDataModel // Do you have a model base type? ;)
{
// Declare members here
}
在我說“在這里聲明成員”的地方,只需聲明屬於您的具體基類的成員(我在說“ BaseStepHandler”)。
之后,在基類BaseStepHandler中實現此接口。
現在,您可以執行所需的操作:
IBaseStepHandler<BaseDataModel> some = new WhateverBaseStepHandlerClass();
// This is possible because T generic parameter is covariant and it can be casted to `BaseDataModel`, or if you don't provide a `T` generic parameter constraint, you could cast it to `IBaseStepHandler<object>` too!
為了了解有關協方差的更多信息,請單擊以下鏈接: http : //msdn.microsoft.com/zh-cn/library/ee207183.aspx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.