日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

虚虚实实,亦假亦真的 ValueTuple,绝对能眩晕你

發(fā)布時(shí)間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 虚虚实实,亦假亦真的 ValueTuple,绝对能眩晕你 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一:背景

1. 講故事

前幾天在寫一個(gè)api接口,需要對(duì)衣物表進(jìn)行分頁查詢,查詢的output需要返回兩個(gè)信息,一個(gè)是 totalCount,一個(gè)是 clothesList,在以前我可能需要封裝一個(gè) PagedClothes 類,如下代碼:

public?class?PagedClothes{public?int?TotalCount?{?get;?set;?}public?List<Clothes>?ClothesList?{?get;?set;?}}static?PagedClothes?GetPageList(){return?new?PagedClothes(){TotalCount?=?100,ClothesList?=?new?List<Clothes>()?{?}};}

在 C# 7.0 之后如果覺得封裝一個(gè)類太麻煩或者沒這個(gè)必要,可以用快餐寫法,如下代碼:

static?(int,?List<Clothes>)?GetPageList(){return?(10,?new?List<Clothes>()?{?});}

這里的 (int, List<Clothes>) ?是什么意思呢?懂的朋友看到 (x,y) 馬上就會(huì)想到它是 .NET 引入的一個(gè)新類:ValueTuple,接下來的問題就是真的是ValueTuple嗎?用ILSpy 看看 IL 代碼:

.method?private?hidebysig?static?valuetype?[System.Runtime]System.ValueTuple`2<int32,?class?[System.Collections]System.Collections.Generic.List`1<class?ConsoleApp2.Clothes>>?GetPageList?()?cil?managed?{IL_0000:?nopIL_0001:?ldc.i4.s?10IL_0003:?newobj?instance?void?class?[System.Collections]System.Collections.Generic.List`1<class?ConsoleApp2.Clothes>::.ctor()IL_0008:?newobj?instance?void?valuetype?[System.Runtime]System.ValueTuple`2<int32,?class?[System.Collections]System.Collections.Generic.List`1<class?ConsoleApp2.Clothes>>::.ctor(!0,?!1)IL_000d:?stloc.0IL_000e:?br.s?IL_0010IL_0010:?ldloc.0IL_0011:?ret}?//?end?of?method?Program::GetPageList

從 GetPageList 方法的 IL 代碼可以很容易的看出方法返回值和return處都有 System.ValueTuple 標(biāo)記,從此以后你可能就會(huì)以為 (x,y) 就是 ValueTuple 的化身 ,是吧,問題就出現(xiàn)在這里,這個(gè)經(jīng)驗(yàn)靠譜嗎?

二:(x,y) 真的是 ValueTuple 的化身嗎

為了去驗(yàn)證這個(gè)經(jīng)驗(yàn)是否靠譜,我需要舉幾個(gè)例子:

1. (x,y) 接收方法返回值時(shí)是 ValueTuple 嗎

為了更加清楚的表述,先上代碼:

????????(int?totalCount,?List<Clothes>?orders)?=?GetPageList();static?(int,?List<Clothes>)?GetPageList(){return?(10,?new?List<Clothes>()?{?});}

現(xiàn)在已經(jīng)知道當(dāng) (x,y) 作為方法返回值的時(shí)候在IL層面會(huì)被化作 ValueTuple,那 (x,y) 作為接受返回值的時(shí)候又是什么意思呢?還會(huì)和 ValueTuple 有關(guān)系嗎?為了去驗(yàn)證,可以用反編譯能力弱點(diǎn)的 dnspy 去看看反編譯后的代碼:

從圖中可以看出,當(dāng)用 (x,y) 模式接收的時(shí)候,貌似就是實(shí)現(xiàn)映射賦值 或者 叫做拆解賦值,是不是有一點(diǎn)模糊,這個(gè) (x,y) 貌似和 ValueTuple 有關(guān)系,又貌似和 ValueTuple 沒關(guān)系,不過沒關(guān)系,繼續(xù)看下一個(gè)例子。

2. (x,y) 在 foreach 迭代中是 ValueTuple 嗎

(x,y) 也可以出現(xiàn)在 foreach 中,相信第一次看到這么玩還是有一點(diǎn)吃驚的,如下代碼:

var?dict?=?new?Dictionary<int,?string>();foreach?((int?k,?string?v)?in?dict){}

接下來繼續(xù)用 dnspy 反編譯一下:

我去,這回就清晰了,從圖中可以看出,我寫的 (x,y) 壓根就沒有 ValueTuple 的影子,說明在這個(gè)場(chǎng)景下兩者并沒有任何關(guān)系,也就是說同樣是 (x,y) ,放在不同位置具有不同的表現(xiàn)形式,這就很讓人琢磨不透了, 可能有些朋友不死心,想看一下 Deconstruct 到底干了什么,知道的朋友應(yīng)該明白這個(gè)新玩法叫做解構(gòu)方法,繼續(xù)看代碼:

public?readonly?struct?KeyValuePair<TKey,?TValue>{private?readonly?TKey?key;private?readonly?TValue?value;public?void?Deconstruct(out?TKey?key,?out?TValue?value){key?=?Key;value?=?Value;}}

有些抬杠的朋友會(huì)發(fā)現(xiàn)一個(gè)規(guī)律,貌似 (x,y) 放在賦值語句的左邊都和 ValueTuple 沒有任何關(guān)系,放在右邊可能會(huì)有奇跡發(fā)生,那到底是不是這樣呢?繼續(xù)硬著頭皮舉例子唄。

3. (x,y) 放在賦值語句的右邊是 ValueTuple 嗎

public?class?Point{public?int?X?{?get;?set;?}public?int?Y?{?get;?set;?}public?Point(int?x,?int?y){(X,?Y)?=?(x,?y);}}

嘿嘿,看這句: (X, Y) = (x, y) 里的 (x,y) 是 ValueTuple 的化身嗎?我猜你肯定是懵逼狀態(tài),是吧,亦真亦假,虛虛實(shí)實(shí),證據(jù)還是繼續(xù)反編譯看唄。

我去,又是和 ValueTuple 一點(diǎn)關(guān)系都沒有,啥玩意嘛,亂七八糟的,莫名其妙。

三:總結(jié)

說 (x,y) 是元組吧,放在 return 中就變成了 ValueTuple ,說 (x,y) 不是元組吧,放在其他處還真就不是的,是不是很疑惑,為了更加形象,在 Point 中再增加一個(gè) Test 方法,對(duì)照一下源碼和反編譯的代碼:

//原始的:public?class?Point{public?int?X?{?get;?set;?}public?int?Y?{?get;?set;?}???????? public?Point(int?x,?int?y){(X,?Y)?=?(x,?y);}public?(int?x,?int?y)?Test(){return?(X,?Y);}}//反編譯的:public?class?Point{public?int?X?{?get;?set;?}public?int?Y?{?get;?set;?}public?Point(int?x,?int?y){this.X?=?x;this.Y?=?y;}[return:?TupleElementNames(new?string[]{"x","y"})]public?ValueTuple<int,?int>?Test(){return?new?ValueTuple<int,?int>(this.X,?this.Y);}}

反正我已經(jīng)惱火了,就這樣吧,少用經(jīng)驗(yàn)推理,多用工具挖一挖,這樣才靠譜!

總結(jié)

以上是生活随笔為你收集整理的虚虚实实,亦假亦真的 ValueTuple,绝对能眩晕你的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。