簡體   English   中英

如何上載泛型類型參數

[英]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泛型最常見的錯誤。 類型參數的泛型不是協變的。

看到:

C#:強制轉換為具有基本類型的通用接口

http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-two.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.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.

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