這幾天忙的暈頭暈腦的,午休取消了,抽煙時間也掐著算,連上廁所的空兒都在想工作那些事兒,沒辦法,搞IT這行,事兒多的時候,1天24小時是不夠用的,必須一天25小時才行。可日子不按咱的想法走,咱只能順著日子過!
忙的時候一糊塗就容易犯錯,這不犯了個菜鳥層級的錯嘛,讓同事好一頓奚落 。事情是這樣的,項目中某個演算法需要做最佳化,在Code review的時候發現在初始化時請求資料庫比較多,而部分資料又是配置型資料(這裡將不頻繁變動的資料且稱為配置型資料),且數量也不多,於是就想到了使用靜態構造來儲存這部分資料,以減少資料庫請求量。由此在最佳化的時候將原來的局部變數變成了全域靜態變數,且在靜態建構函式內構造一次,這樣一來問題就出來了,這也怪我太急功近利,因為事兒比較多,也就沒留個心眼,結果吃大虧了。
說到這裡,看這文章的老鳥們肯定明白了個中緣由(相信也有不少一看題目就能猜到個八九不離十的鳥人們)。閑話先不說,”翠花,上代碼!”
public class StaticBug
{
static Dictionary<int,Bug> BugDictionary = new Dictionary<int,Bug>();
static StaticBug()
{
InitBugDictionary();
}
private Bug ErrorGetBug(int bugId)
{
//錯誤的方法.
Bug bug = null;
if (BugDictionary.ContainsKey(bugId))
{
bug = BugDictionary[bugId];
if (bug != null)
{
bug.BugCount++;//並不希望改變BugDictionary中Bug對象的BugCount屬性值.
}
}
else
{
InitBugDictionary();
if (BugDictionary.ContainsKey(bugId))
{
bug = BugDictionary[bugId];
if (bug != null)
{
bug.BugCount++;//並不希望改變BugDictionary中Bug對象的BugCount屬性值.
}
}
}
return bug;
}
}
public class Bug
{
public int BugId{ get; set; }
public string BugTitle { get; set; }
public string BugContents { get; set; }
public int BugCount { get; set; }
public static Dictionary<int, Bug> GetBugs()
{
//Do some thing to get bugs.
return new Dictionary<int, Bug>();
}
}
從代碼中可以看到對bug變數的錯誤操作。若不希望改變BugDictionary中Bug對象的BugCount屬性值,正確的代碼應該是:
private Bug RightGetBug(int bugId)
{
Bug bug = null;
Bug tempBug = new Bug();
if (BugDictionary.ContainsKey(bugId))
{
bug = BugDictionary[bugId];
if (bug != null)
{
tempBug.BugId = bug.BugId;
tempBug.BugTitle = bug.BugTitle;
tempBug.BugContents = bug.BugContents;
tempBug.BugCount = bug.BugCount;
tempBug.BugCount++;
}
}
else
{
InitBugDictionary();
if (BugDictionary.ContainsKey(bugId))
{
bug = BugDictionary[bugId];
if (bug != null)
{
tempBug.BugId = bug.BugId;
tempBug.BugTitle = bug.BugTitle;
tempBug.BugContents = bug.BugContents;
tempBug.BugCount = bug.BugCount;
tempBug.BugCount++;
}
}
}
return tempBug;
}
從上面代碼可以看出使用了一個臨時Bug對象來接收bug的屬性值,然後BugCount++,避免了修改BugDictionary。
相信不少新手在使用static的時候會遇到這個錯誤,也相信有不少想我這樣的老手一不謹慎就造成了這樣的錯誤。造成錯誤的原因簡單,但從3千多行代碼中排除bug,談何容易!因此,各位兄弟姐妹們在使用static變數的時候要謹慎。不只如此,在使用單例模式的時候更要謹慎,相比較起來,單例模式出bug要比我這情況容易排查多了。
寫此菜鳥型文章,鬥膽放在首頁上拋磚引玉,希望比我更老的鳥們提點兒珍貴的意見!
PS:沒想到招來罵聲一片!-----------------PS2:我還是說說我的本意吧,其實我是不希望對BugDictionary中的元素做任何改變。嗯,沒錯,歸根究底還是參考型別造成的,從這個角度來說跟static沒關係。但是從static角度來考量,假如沒有使用static,就不會出這問題了。我可以直接取BugDictionary裡元素,經過加工後返回。所以,綜合來說,是我在使用static時疏忽了不能對BugDictionary進行修改這一點造就了這個錯誤。我只希望能對其他人有個警醒作用!評論的兄弟們你們說的都沒錯,但是考慮問題角度不同,給出的觀點也是不同。-----------------PS3:其實搞.net的都知道.net裡總的有2種資料類型:實值型別、參考型別,但為什麼卻還是有不少人頻頻的遇到"未將對象引用設定到對象執行個體"的異常呢?這值得我們思考,雖然這是低級錯誤,但為什麼我們總是頻繁犯這些低級錯誤呢?難道這些不值得我們思考嗎?