Effective C# 01.偏好隱含型別的區域變數 Effective C# 01.偏好隱含型別的區域變數(Prefer Implicitly Typed Local Variables)

Published on Saturday, September 21, 2024

這個建議做法推薦我們多使用 var(隱含型別的區域變數),讓 compiler 自行推斷實際的類型。 當編譯器看到 var 關鍵字時會參考 = 右側的運算式,背後宣告這個區域變數的型別,可以省掉我們自行判斷宣告型別的流程。

第二個好處是能避免變數被錯誤宣告為不正確的型別。常見的問題就是 IEnumerable<T>IQueryable<T> 轉換錯誤導致的性能問題。

當我們使用 EFCore 搭配 LINQ 來存取資料庫數據時,會使用到LINQ to ObjectsLINQ to SQL 來篩選或排序我們想要的資料。

由於 IEnumerable<T>IQueryable<T> 在使用上相似,因此在進行 LINQ to SQL 操作時, 有時會強制將結果變數宣告為 IEnumerable<T>。然而,這種強制轉換會使程式無法享受 IQueryable<T> 所帶來的好處。 使用 var 關鍵字讓編譯器自動推斷變數類型,則能避免此問題並充分利用 IQueryable<T> 的特性。

使用 var 搭配有可讀性的變數名稱,能幫助開發者更容易理解變數的用途。例如,當我們看到 Dictionary<int, Queue<string>> 這樣的類型時, 可能需要花些時間思考它的用途。然而,這種明確宣告的類型並不一定能幫助理解。因此,不如直接使用 var 並將變數名稱改為更具意義的名稱, 例如 jobsQueuedByRegion,這樣反而能讓我們更快地理解變數的目的和功能。

有可讀性的變數名稱

這個例子中我們可以很輕易的從右側的運算式推測出 foo 變數的類型為 MyType

var foo = new MyType();

從這個 Factory 也能夠推測出這個 thing 變數應該是跟 Account 類型有相關。

var thing = AccountFactory.CreateSavingAccount();

但是也有可能沒辦法從右側的運算式推測出具體的類型,這個例子中 result 這個名稱沒辦法從語意推測出類型或涵義, 並且右側的 DoSomeWork 方法回傳類型也很不明確。

var result = someObject.DoSomeWork(anotherParameter);

所以可以從 result 這個變數名稱下手,至少讓開發者推測這個變數應該和 Product 類型有關。

var HighestSellingProduct = someObject.DoSomeWork(anotherParameter)

這也產生另一種可讀性的問題,可能第一個工程師推斷這個變數是 Product 類型,但第二個工程師可能覺得是另一個衍生類型 HighestSellingProduct。 假設我們想要的類型為 Product 但編譯器推斷成 HighestSellingProduct 那麼這種情況就不應該使用使用 var

數值轉型問題

在宣告數值相關的變數時要額外小心,var 推測可能會導致精度的喪失。 在下方的例子中,GetMagicNumber 方法回傳的類型為 decimal,同時宣告的變數 f 類型也會為 decimal,最後在計算 total 時也會知道類型為 decimal, 另一個常見的錯誤是計算 total1 時,右側沒有指定類型導致結果精度丟失。

void Main()
{
	var f = GetMagicNumber();
	var total = 100 * f / 6;
	Console.WriteLine($"Declared Type: {total.GetType().Name}, Value: {total}");
	
	decimal total1 = 100 * 10 / 6;
	Console.WriteLine($"Declared Type: {total1.GetType().Name}, Value: {total1}");
}

public decimal GetMagicNumber()
{
	return 10;
}

Declared Type: Decimal, Value: 166.66666666666666666666666667
Declared Type: Decimal, Value: 166

Summary

  1. 除非開發者必須看到宣告型別才能理解程式,否則就使用 var 宣告區域變數。
  2. 明確宣告數值類別的型別(int、float、double...),不要使用 var 宣告區域變數。
  3. 其他情況就使用 var 搭配有可讀性的變數名稱。