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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

我犯了一个错误,您能指出吗?(结论)

發(fā)布時(shí)間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 我犯了一个错误,您能指出吗?(结论) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

其實(shí)許多朋友已經(jīng)在回復(fù)中發(fā)現(xiàn)問題所在了,其中最早指出錯(cuò)誤的是狼Robot同學(xué),他說:

每個(gè)T都會(huì)使用一個(gè)新的連接。

泛型類中的靜態(tài)變量會(huì)因?yàn)門的不同而產(chǎn)生不同的值,也就是說每個(gè)T所訪問的靜態(tài)變量都是獨(dú)立的。

正是這個(gè)原因,導(dǎo)致UserRepository和ArticleRepository,雖然似乎都繼承了Repository<T>類,但是因?yàn)槭褂昧瞬煌腡類型,所以實(shí)際上它們是不同的類,而它們的ConnectionKey值是不同的。使用不同的ConnectionKey,就無法從ResourceManager中獲得同一個(gè)Connection對象了。以下的代碼可以很輕易地證明這一點(diǎn)。

public static class MyClass<T> {public static readonly Guid Key = Guid.NewGuid(); }class Program {static void Main(string[] args){Console.WriteLine("int: " + MyClass<int>.Key);Console.WriteLine("string: " + MyClass<string>.Key);Console.ReadLine();} }

由于MyClass<int>和MyClass<string>是不同的類,因此它們的Key也是分離的,值也不同(Guid.NewGuid()了兩次)。因此,在泛型類中定義靜態(tài)字段的時(shí)候一定要注意:不同泛型參數(shù)生成的具體類(無論是值類型還是引用類型),它們的靜態(tài)字段是獨(dú)立的。這點(diǎn)說起來簡單,但是有時(shí)候不太容易意識到。例如,我之所以犯這個(gè)錯(cuò)誤,正是因?yàn)樵綬epository類是非泛型的,而后面由于某些原因才將其改為泛型。這樣的錯(cuò)誤使用單元測試也很難檢查出來,非常隱蔽。

不過解決方案也非常簡單,例如隨意給出一個(gè)具體的Guid,而不是每次都使用Guid.NewGuid生成新的值:

public abstract class Repository<T> {private readonly static Guid ConnectionKey = new Guid("a18b2f49-cafc-43e3-a49d-3fac91701394"); }

這樣,雖然UserRepostory和ArticleReposityr的ConnectionKey還是不同的Guid對象,但是它們的“值”是相同的(也就是說GetHashCode相同,Equals返回true),對字典來說它們是相同的“鍵”。當(dāng)然,還有其他解決方案,例如把ConnectionKey放到其它非泛型的類中去即可。

有些朋友還提出了其他的觀點(diǎn)。例如,ResourceManager是不同的實(shí)例,怎么做到“保留Connection對象”呢?其實(shí)只需要它們都基于一個(gè)合適的數(shù)據(jù)容器就可以了,比如都基于HttpContext.Current。這方面的例子很多,比如不同的Connection對象都是訪問同一個(gè)數(shù)據(jù)庫的。因此,這里不是問題。

還有,有朋友認(rèn)為共享Connection對象的做法不好。其實(shí)這也是沒有關(guān)系的,因?yàn)檫@里“共享”的范圍只是“單個(gè)請求”。對于ASP.NET請求來說,這些操作都是同步的,因此不會(huì)產(chǎn)生線程安全的問題。而一個(gè)請求的時(shí)間很短,因此Connection的生命周期也不長。這樣的實(shí)踐很多,例如NHiberante推薦為每個(gè)請求分配一個(gè)唯一的ISession對象(Sharp Architecture就是怎么做的)——這就相當(dāng)于一個(gè)Connection——不過我不喜歡,因此我使用的做法是為單個(gè)請求按需創(chuàng)建多個(gè)Session,但是共享一個(gè)Connection對象。此外,共享Connection對象還有其他一些好處,例如不會(huì)引發(fā)需要MSDTC的分布式事務(wù)。

這個(gè)問題已經(jīng)解決了。但是上文的評論中還有其他一些討論。例如,您知道為什么下面的代碼中,兩個(gè)時(shí)間是相同的嗎?

public static class MyClass<T> {public static readonly DateTime Time = DateTime.Now; }class Program {static void Main(string[] args){Console.WriteLine("int: " + MyClass<int>.Time);Thread.Sleep(3000);Console.WriteLine("string: " + MyClass<string>.Time);Console.ReadLine();} }

它們輸出的結(jié)果是:

int: 2009/9/8 15:30:06 string: 2009/9/8 15:30:06

這和我們的理解好像不同,因?yàn)楫?dāng)我們訪問MyClass<string>的時(shí)候,應(yīng)該比MyClass<int>要晚3秒鐘,但為什么時(shí)間是相同的呢?那么我們把測試代碼換一種寫法,會(huì)更清楚一些:

public static class MyClass<T> {public static readonly DateTime Time = GetNow();private static DateTime GetNow(){Console.WriteLine("GetNow execute!");return DateTime.Now;} }class Program {static void Main(string[] args){Console.WriteLine("Main execute!");Console.WriteLine("int: " + MyClass<int>.Time);Thread.Sleep(3000);Console.WriteLine("string: " + MyClass<string>.Time);Console.ReadLine();} }

我們增加了會(huì)輸出一些內(nèi)容的GetNow靜態(tài)方法,Main方法的開頭也打印出一些內(nèi)容。這段代碼輸出如下:

GetNow execute! GetNow execute! Main execute! int: 2009/9/8 15:34:31 string: 2009/9/8 15:34:31

可以發(fā)現(xiàn),在Main方法執(zhí)行之前,MyClass<int>和MyClass<string>的GetNow就被調(diào)用了。因此,它們的Time字段是相同的。不過,如果我們在MyClass<>中增加一個(gè)空的靜態(tài)構(gòu)造函數(shù),結(jié)果就會(huì)有所不同:

public static class MyClass<T> {public static readonly DateTime Time = GetNow();private static DateTime GetNow(){Console.WriteLine("GetNow execute!");return DateTime.Now;}static MyClass() { } }

輸出如下:

Main execute! GetNow execute! int: 2009/9/8 15:40:12 GetNow execute! string: 2009/9/8 15:40:15

由于GetNow方法只在“第一次”用到MyClass<int>和MyClass<string>時(shí)執(zhí)行,因此獲得的時(shí)間是不同的。不過,為什么加入了靜態(tài)構(gòu)造函數(shù)之后,Time字段的初始化時(shí)機(jī)就有所改變呢?那是因?yàn)镮L中beforefieldinit修飾在作怪。關(guān)于這一點(diǎn),許多書中都有提及。園子中的Artech同學(xué)對這個(gè)問題也有所分析。

在目前的情況下,泛型類這一性質(zhì)給我們造成了一定的麻煩。但是,只要我們使用得當(dāng),它也可以在某些場景下簡化開發(fā)。因此,最后請大家和我一起在心中默念:信腦袋,得永生,信腦袋,得永生……

from: http://blog.zhaojie.me/2009/09/i-made-a-mistake-can-you-figure-it-out-answer.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的我犯了一个错误,您能指出吗?(结论)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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