何謂弱型別? 

MSDN 上面有這麼一段對弱型別的描述:
未宣告的變數以及不具資料型別的宣告變數都會指定為 Object 資料型別,這會加快程式的撰寫,但可能會使程式的執行變慢。
弱型別除了不支援 Visual Studio 的 IntelliSense 之外,另一個缺點就是要等到「執行時期」才會發生錯誤,無法在「編譯時期」就能發現錯誤,進而導致在開發或是偵錯上的不便,舉一個較為簡單的例子來做說明,例如大家在專案裡最常接觸並且使用的「DataSet」或「DataTable」就是弱型別的一種,尤其是在撈取資料庫資料的時候,大家一開始接觸的一定就是「DataTable」,所以下面就以「DataTable」來示範當使用弱型別時,最常遇到的三種無法在「編譯時期」就發現的錯誤。

這邊示範的資料庫為「北風資料庫」的 Employees 資料表。

假設我們要取得 EmployeeID, LastName, FirstName, Title, BirthDate 這5個欄位。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
using (SqlConnection SqlCon = new SqlConnection(strConn))
{
    string strComm = "select EmployeeID, LastName, FirstName, Title, BirthDate from Employees";
    SqlCommand sqlComm = new SqlCommand(strComm, SqlCon);
    try
    {
        SqlCon.Open();
        DataTable table = new DataTable();
        SqlDataReader reader = sqlComm.ExecuteReader();
        table.Load(reader);
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

Employees

第一種:在 SQL Command Key 錯欄位名稱,像下面這樣,我把 EmployeeID 欄位名稱的 l Key 成 1,等到程式執行時,才會跳出錯誤。

1
string strComm = "select Emp1oyeeID, LastName, FirstName, Title, BirthDate from Employees";

Employees

第二種:要取得 DataTable 第一筆資料列的 EmployeeID 值,若是 Key 錯欄位名稱,也是要等到程式執行時,才會發現錯誤。

1
string EmpID = table.Rows[0]["Emp1oyeeID"].ToString();

Employees

第三種:宣告錯誤的型別,有時我們會遇到很多欄位的資料表,在處理這麼多的欄位資料時,難免會疏忽掉型別的問題,導致在取值時,定義了錯誤的型別,這邊我先在 Employees 資料表新增一個 Test 欄位並設成 decimal(18, 2),接著透過下述的方式來取值,一樣也是要等到程式執行時,才會發現指定了錯誤的型別。

1
int test = (int)table.Rows[0]["Test"];

Employees


何謂強型別? 

MSDN 上面對強型別的描述:
指定所有變數的資料型別稱為「強型別指定」(Strong Typing)。
使用強型別指定有以下幾點好處:

  • 讓 IntelliSense 能夠支援變數。 這能讓您在輸入程式碼時看到變數的屬性及其他成員。
  • 可以利用編譯器型別檢查, 這能找出可能因錯誤 (例如溢位) 而在 Run Time 失敗的陳述式。 這也能夠偵測在不支援變數的物件上所進行的方法呼叫。
  • 執行程式碼的速度較快。

以上摘錄自 MSDN 有效率地使用資料類型


這邊我先將建立一個 Employees 類別,屬性就只建立 EmployeeID, LastName, FirstName, Title, BirthDate 與剛才新增的 Test

1
2
3
4
5
6
7
8
9
class Employees
{
    public string EmployeeID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Title { get; set; }
    public DateTime BirthDate { get; set; }
    public decimal Test { get; set; }
}

接著宣告一個 List<Employees> ,再將撈出至 DataTable 的資料存放在 List 裡,以供後續存取運用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
List<Employees> employees = new List<Employees>();
foreach (DataRow row in table.Rows)
{
    employees.Add(new Employees
    {
        EmployeeID = row["EmployeeID"].ToString(),
        LastName = row["LastName"].ToString(),
        FirstName = row["FirstName"].ToString(),
        Title = row["Title"].ToString(),
        BirthDate = Convert.ToDateTime(row["BirthDate"]),
        Test = Convert.ToDecimal(row["Test"])
    });
}

這時,我們在後續存取運用時,就可享有 IntelliSense 所帶來的便利與明確的型別定義,若發生錯誤,在編譯時期即可發現。

例如要存取 employees 裡的物件時,只要鍵入 Dot 後,IntelliSense 即會自動幫我們帶出可供存取的公開屬性,光是這點好處就可避免先前直接存取 DataTable 時,Key 錯欄位名稱的問題
Employees

若是指定了錯誤的型別,IDE 也會直接提示我們型別錯誤且也無法進行 Compiler Employees

透過上述二點就能明確感受到強型別所帶來的好處!尤其是當今天遇到資料表的欄位一大堆且名稱又臭又長時,若是使用弱型別的 DataTable 來進行存取,光是要 Key 那些欄位名稱而且還要打正確,相信就頭很痛了,當然 Debug 就更不用說了,若發生錯誤則要等到執行時期才會跳出錯誤。
當然上述的範例是為了示範,所以才必需要自己建立 Employees 類別,實際運用上則會透過 Linq To SQL 或是 Entity Framework 來幫我們自動產生資料表所對應的POCO類別,後面我會再針對這部份來做介紹,若您現在仍還在使用弱型別的方式進行開發,建議您要開始改用強型別來進行開發,一來可以享用強型別的好處,二來這也是現今的的趨勢。