最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

C# 方法的簽名上最多可以由多少個關鍵字構成?

2023-08-12 22:48 作者:SunnieShine  | 我要投稿

這是一個非常有趣的問題??赡芪覀冊谄綍r使用的過程之中并不會這么去用,但是這對我們了解一些新鮮、罕見的語法有一定的蛇皮幫助。

題目介紹

首先,我們知道,一個方法需要有簽名(Signature)一說。它指的是我們在書寫方法的時候,那個方法的頭部。比如下面的這個代碼:

該方法具有兩個修飾符:publicstatic。這很好理解。一個方法無需修飾符的時候,它默認會和 C 語言的理解進行一定程度上的兼容和匹配。只不過,static 在 C# 里已經具有一個比較大的變化。

那么,請問一個方法最多可以有多少個修飾符構成呢?這一次我們把問題“廣義化”到,返回值類型如果是關鍵字也算修飾符的一部分。也就是說,這個問題如果改成這樣的話,那么剛才的這個 Main 方法我們將算成三個修飾符。而題問的是,一個方法最多可以由多少個修飾符構成。

很明顯,這個問題可能在不同的 C# 語言版本里有不一樣的答案。我們目前將 C# 12 納入其中進行計算,那么它應該是多少呢?

開始構造

首先我們需要非常熟悉 C# 的修飾符的用法。C# 的修飾符非常多,我們主要在面向對象里會用到如下的修飾符種類:

  • 訪問修飾符(publicprotected 這些)

  • 多態(tài)修飾符(new、virtual、abstractsealed

  • 靜態(tài)修飾符(static 這一個)

  • 一些普通的類型關鍵字(int、string 等)

但是,光靠這些是不夠長的。我們舉個例子。

我們知道,訪問修飾符里有一個不起眼的修飾級別:protected internal。這個級別是組合關鍵字用法,表示的是該成員在當前程序集里可以隨便看到;但是出了程序集之后,你只能在從這個成員的對應類型進行派生了之后才可以看到。那么,它因為用到兩個關鍵字,所以我們納入進來。

其次是 static。我們一般習慣把靜態(tài)的修飾符放在訪問修飾符旁邊,這樣一眼就看得到。

然后是多態(tài)修飾符。這次我們知道的是,面向對象不允許我們使用 abstract 在靜態(tài)成員上,所以多態(tài)修飾符非得加進來的話,只能用 new。

最后算上返回值類型,隨便挑一個吧。

挑選完畢后,一共是這樣的情況:

這樣的話,把 int 算進去就有 5 個了。但這肯定不是極限。

一些不太常用的修飾符

我們再來想一想。這個問題針對的是方法,而方法在 C# 里有一個比較不起眼的特性教分部方法(Partial Method)。這個特性允許我們將方法拆解為聲明部分和代碼實現(xiàn)部分,存儲在兩個不同的文件之中。這樣做的目的其實是為了便于編譯器生成代碼的時候,在不改動源代碼的時候可為類型進行擴展;也可以往分部方法上標記特性,這樣可以達到一些比較方便的生成行為。

但,這個方法是非 void 返回的,而且訪問修飾符級別也不是 private,這意味著我們不能使用分部方法的特性。其實不然。從 C# 9 開始,分部方法允許我們使用它來作用于任何方法。所以,代碼可以這樣:

很好。這樣夠了嗎?并不夠。C# 9 允許的分部方法雖然推廣到任意方法之上,但很遺憾的是,因為方法本身帶有返回值類型,訪問修飾級別也并非原有的 private,所以可能在使用代碼的時候造成副作用。而分部方法有一個非常神奇的規(guī)則是,它可以不實現(xiàn)。如果你將分部方法的聲明部分寫出,哪怕你不去實現(xiàn)它,你在代碼里也可以使用該方法。雖然它沒有實現(xiàn),它等于是在運行時沒有效果,但它并不影響編譯。如果你實現(xiàn)了,你就可以獨立在單獨的文件里實現(xiàn),讓方法跑起來。這樣甚至不用改動原來的文件。

但是,這特性在 C# 9 里,因為訪問修飾符、返回值類型等因素,該方法就無法保證實現(xiàn)的安全性。因此,它必須給出實現(xiàn)部分。因此,我們只能將其拆解為兩個文件。為了保證該方法簽名的穩(wěn)定性。

這樣似乎已經到了 6 個關鍵字的地步了。其實并不夠。我們還有一個殺手锏:extern 關鍵字。

該關鍵字可謂在 C 語言里用得特別多。在 C# 里基本就遇不到了??赡苣銓?P/Invoke(互操作性)的時候會用到它。它表示該成員的實現(xiàn)部分不是 C# 來做的。你往成員的修飾符里加了它之后,成員即使直接以分號結尾也不會影響程序的編譯,因為編譯器認為你的代碼走的是別的語言實現(xiàn)的、或者是 C# 實現(xiàn)的代碼,但放在了獨立的 dll 文件之中。

因此,加上該修飾符,我們可以達到 7 個修飾符的地步,且不需要給出實現(xiàn)。

還沒到達巔峰。接下來我們用到的是 unsafe 關鍵字。

該關鍵字用來表示該代碼段落是不安全的。換言之,該段落的代碼用到了 C# 里的指針操作。比如 -> 運算符、void* 以及 C# 9 里才有的函數(shù)指針。假設我們將返回值替換為函數(shù)指針類型,那么方法聲明就有些“耍賴”了——因為函數(shù)指針的聲明是允許遞歸的。比如說,delegate* managed<void> 表示返回 void 的、由 C# 程序集里給定的靜態(tài)方法,指向這樣的方法的指針;而返回值替換為函數(shù)指針:delegate* managed<delegate* managed<void>> 也算允許存在的。

但是,這樣做太耍賴了。于是問題我們不允許這么干。但是,即使方法聲明里不帶指針,但我們能不能當修飾符加進去呢?答案是可以的。下面的代碼就可以展示出這樣的效果:

現(xiàn)在已經達到了驚人的 8 個修飾符了。這是答案了嗎?No。

C# 7 開始允許我們將返回值聲明為引用返回,這樣的方法將返回一個對象的引用。ref T 表示返回一個 T 類型實例的引用;而 ref readonly T 則表示一個 T 類型的只讀引用,即從上面?zhèn)飨聛恚銦o法改動它指向的對象的值。比如對對象進行自增操作,它改變了內部的數(shù)值;但你可以用到它的引用來做一些事情。

那么這樣的話,就好說多了。我們可以使用 ref readonly int 組合來達到這個方法聲明的巔峰:

很好。這樣我們就達到了 10 個修飾符的地步。這便是最多的情況。

那么,這是答案嗎?No??墒俏覀円呀洘o法再繼續(xù)進行推廣了啊。static 修飾符意味著方法不能追加 readonly 修飾符來表示方法不改變 this 的內部數(shù)值(如果 class C 改成 struct C 的話);而 async 修飾符又不允許我們使用引用,而該方法返回了一個只讀引用。這看起來并不能繼續(xù)了;而 override 則可以用于 class 類型,但這個方法是靜態(tài)的,你也無法繼續(xù)進行重寫之類的操作。

那我們構造一個?

請仔細理解該例子。這個例子的 B 類型里最后的這個實現(xiàn)部分用到了最多的情況,而且用的是實例的實現(xiàn)模式,沒有用 static 關鍵字。這樣的目的是為了可以用 override 關鍵字;而這樣也可以使用 sealed override 或者是 abstract override 組合修飾來達成派生的方法重寫模式。

另外,該例子的其他修飾符也都用上了,但很遺憾的是,這例子也是 10 個關鍵字。

那,真的沒有辦法繼續(xù)了嗎?答案是否定的。

接近答案

讓我們發(fā)散地想一想。既然靜態(tài)成員無法抽象,那有沒有可能,我們讓靜態(tài)成員抽象起來呢?C# 11 的接口靜態(tài)抽象成員(Static Abstract Members in Interface)剛好就允許了這一點。雖然它本來是用于數(shù)字泛型參數(shù)化的。

于是,我們找到了最多的關鍵字的情況,11 個。

其他問題

1、override 不能用構造放進去嗎?

很遺憾,做不到。因為接口不能用 override 修飾符。而如果你基于普通類型的話,又無法使用靜態(tài)抽象成員了,因此沒可能同時兼具。

2、還能更多嗎?

不能。這是本題的最終解決方案。不過 C# 可能會在以后允許在接口里聲明 readonly 修飾的成員來保證對象的 this 指針的內部數(shù)值只讀。于是,它還能加一個修飾符,成為最多的情況。

與此同時,比較新的 scoped 關鍵字目前只能修飾在參數(shù)和臨時變量上,我們無法將其放在別的地方,所以 scoped 關鍵字在這個題目里用不著。

另外,如果我們將運算符也算方法的話,我們可能會考慮出更多的組合。比如說運算符就可以多一個 checked 修飾符(operator checked 的聲明),但它不能改變訪問級別,它只能是 public 的,所以此時訪問修飾符又只能用一個關鍵字了。怎么都做不到。


C# 方法的簽名上最多可以由多少個關鍵字構成?的評論 (共 條)

分享到微博請遵守國家法律
枣阳市| 左权县| 鄂尔多斯市| 长海县| 黄骅市| 永丰县| 娄底市| 河曲县| 海原县| 东阳市| 新绛县| 临朐县| 高州市| 峡江县| 临澧县| 平罗县| 威宁| 黄陵县| 大余县| 南靖县| 灵台县| 松桃| 澄城县| 遵化市| 宜春市| 镇巴县| 新建县| 沙雅县| 莒南县| 定边县| 浮山县| 炎陵县| 鄂尔多斯市| 乌拉特中旗| 奉贤区| 昌吉市| 民勤县| 南靖县| 沙坪坝区| 肇东市| 类乌齐县|