這個做法提到了 Stringly Typed 這個概念,字串型別這個翻譯有點模糊表達不夠精確,這個做法主要是在討論弱型別的問題。 通常在使用外部涵式庫或者使用反射功能時會碰到需要使用弱型別字串來當作參數。

以這個 Car 類型為例子,SetName 方法需要傳入一個參數 carName。

public class Car
{
	private string name;
	public string Name
	{
		get => name;
	}

public void SetName(string carName)
{
	if (carName == null || carName.Length < 4)
		throw new ArgumentNullException("carName", $"carName cannot be too short");

	name = carName;
}

接下來故意違反規則並拋出 ArgumentNullException。

carName cannot be too short (Parameter 'carName')

這個類型未來會碰到一個問題,那就是當 carName 參數改名時因為是錯誤訊息是弱型別的,所以需要手動去修改也有可能漏掉。 所以就開發出了 nameof() 來處理這個問題,我們修改範例改成使用 nameof()

public class Car
{
	private string name;
	public string Name
	{
		get => name;
	}

	public void SetName(string carName)
	{
		if (carName == null || carName.Length < 4)
			throw new ArgumentNullException(nameof(carName), $"{nameof(carName)} cannot be too short");
			
		name = carName;
	}
}

這樣修改會發現參數變成強型別了,我們之後就可以使用 ide 的重構工具直接處理重命名的工作,也不會有漏掉沒修改的問題。

另外一個 Stringly Typed 的例子就是操作資料庫,第一種是用 ado.net 直接撰寫 SQL 語句來進行操作,另一種就試用 EFCore 搭配 LINQ 來操作。

使用 ado.net 直接撰寫撰寫 SQL 語句缺點也很明顯,那就是編譯器沒辦法及時知道語句是否有打錯字或者欄位根本不存在。

string queryString =
            "SELECT ProductID, UnitPrice, ProductName from dbo.products "
                + "WHERE UnitPrice > @pricePoint "
                + "ORDER BY UnitPrice DESC;";

使用 LINQ 就可以避免打錯字或不存在等問題,因為是強行別的編譯器會即時發現。

var query =
   from c in db.Customers
   where c.Name.StartsWith ("A")
   orderby c.Name
   select c.Name.ToUpper();

Summary

這個做法主要是在講討論 Stringly Typed 會造成程式碼壞味道的問題,還有 nameof 這個方法,我們應該盡量避免程式碼有 Stringly Typed 這種寫法。