C# 值类型的局限性
? ? ? 如果程序希望使用一個(gè)值類型實(shí)例來進(jìn)行同步,通常都會是錯(cuò)誤(bug)。但運(yùn)行時(shí)應(yīng)該認(rèn)為這是非法并拋出異常嗎?在下面的代碼示例中如果兩個(gè)不同的線程同時(shí)調(diào)用同一個(gè)Counter 實(shí)例的Increment 方法,將會發(fā)生什么?
class Counter{private int _i;public int Increment(){lock (_i){return ++_i;}}}? ? ? ?當(dāng)我們打算這樣做的時(shí)候,會發(fā)現(xiàn)這樣一個(gè)意想不到的問題:C#編譯器不允許lock關(guān)鍵字使值類型。不過,我們已經(jīng)熟知lock關(guān)鍵字的內(nèi)部原理,可以變通一下:
class Counter{private int _i;public int Increment(){bool acquired = false;try{Monitor.Enter(_i, ref acquired);return ++_i;}finally{if (acquired) Monitor.Exit(_i);}}}? ? ? ?這樣一來,程序就引入了一個(gè)錯(cuò)誤(bug)。多個(gè)線程能夠同時(shí)進(jìn)入鎖內(nèi)修改_i,而且調(diào) Monitor.Exit還會拋出異常.Monitor.Enter 方法接收的是System.Object類型的參數(shù),是一個(gè)引用,而我們傳遞的是值類型(按值傳遞)。盡管此時(shí)(在需要引用的地方傳遞值),我們所傳遞的值并沒有被更改,但是傳遞給 Monitor.Enter 方法的值與傳遞給Monitor.Exit方法的值具有不同的標(biāo)識。類似地,在一個(gè)線程里傳遞給Monitor.Enter方法的值,與另一個(gè)線程里傳遞給Monitor.Enter的值也具有不同的標(biāo)識。如果我們在需要引用的地方(按值)傳遞值,就不能獲得正確的鎖語義。
? ? ? ?當(dāng)方法返回引用類型時(shí),如果我們返回了一個(gè)值類型,在語義上也不是非常合適。例如,下面的代碼:
object GetInt() { int?i?=?42;return?i;?} object obj= GetInt();? ? ? GetInt方法按值返回一個(gè)值類型,然而調(diào)用者期望方法返回的是引用類型。方法本可以返回在方法執(zhí)行時(shí)存儲i的棧位置,但得到的將是到無效內(nèi)存地址的引用,因?yàn)榉椒ǖ臈瑫诜椒ǚ祷厍扒蹇铡_@說明默認(rèn)情況下按值復(fù)制的值類型語義,并不適合需要對象引用(指向托管堆)的地方。
技術(shù)群:添加小編微信并備注進(jìn)群
小編微信:mm1552923 ??
公眾號:dotNet編程大全? ? ??
總結(jié)
以上是生活随笔為你收集整理的C# 值类型的局限性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 统计 Github 2021 贡献过的开
- 下一篇: .NET6之MiniAPI(十三):健康