泛型參數轉換的問題

泛型不一樣參數類型生成的對象是相互獨立的。函數

//
Tuple<string> ts;
Tuple<object> to;
//ts to 是兩個類型的對象。

不少時候,咱們但願實現 to = ts 這種操做,爲何?由於看上去它應該如此。spa

爲了達到這個目的,就要解決「泛型參數轉換的問題」,這個問題的知識點是in out 泛型變體。老實說,這個問題自己不困難,只是很是不直觀,很容易讓人忘記。code

首先一點,爲了實現to = ts,其實是有前提的,那就是該參數只能用在「返回類型」上。對象

//
delegate object FuncObj();

FuncObj func = ()=>"string";

func之因此成功,就是由於string 能夠轉換成 object。當「用戶」調用func,但願獲得的是object對象,而string也是object對象,因此沒有任何問題。blog

這裏的關鍵是學會採用"用戶"的視角分析問題。接口

//A
delegate void FuncObj2(object obj);
FuncObj2 func2 = (string str)=>{};
//B
delegate void FuncStr(string str);
FuncStr func3 = (object obj)=>{};


分析這兩組代碼,哪個更加合理?string

在用戶角度,它使用的是func2 和 func3class

用戶使用func2,傳遞的對象必然是object,但實際處理的函數是(string)=>{},object是沒法轉換成string的,因此很不合理。泛型

用戶使用func3,傳遞的對象只能是string,而實際處理的函數是(object)=>{},string 是能夠轉換成object的,因此是合理的。lambda

固然這兩組代碼都是不成立的,由於函數參數類型不匹配。

可是泛型提供了一個方法,讓類型不匹配的對象之間可以隱式轉換!它實現的邏輯就是上面分析的。

//out 修飾返回類型
delegate ResultType FuncOut<out ResultType>();
//in 修飾參數類型
delegate void FuncIn<in ParamType>(ParamType param);

//這是一開始咱們想作到的目標
FuncOut<object> fun4 = () => "string";
//這個效果剛好相反
FuncIn<object> funcobj = (object obj) => { };
FuncIn<string> fun5 = funcobj;

//注意,泛型變體通常只能和泛型變體之間隱式轉換
//lambda表達式會自動轉換成參數相同的泛型變體,但沒法接着作變體之間的隱式轉換,因此須要funcobj來過渡

out修飾返回類型,in修飾參數類型,仍是挺形象的,可是要注意泛型in參數,和out參數正好相反。

開始咱們想實現 to = ts,只是看到問題的一半,實際上泛型是存在 ts = to的可能性的,但願讀者能理解這一點。

總結:

out : to = ts;

in : ts = to;

沒有修飾:to,ts徹底獨立。

---------------------------(備註)-------------------------------
out 參數:只能用在返回類型。

in 參數:只能用在參數。

沒有修飾:任意位置。

---------------------------(備註2)------------------------------

in、out泛型參數只能用在委託和接口上面。

//綜合運用
delegate ResultType FuncInOut<in ParamType, out ResultType>(ParamType param);

FuncInOut<object, string> funcobj2 = (object obj) => "string";
            
FuncInOut<string, object> func6 = funcobj2;
相關文章
相關標籤/搜索