C# var資料型態之詳解

  • 26680
  • 0
  • LINQ
  • 2010-05-20

C# var資料型態之詳解

C# 3.0後增加了一種新的資料型態var,目前看到越來越多人濫用這個資料型態(包含一些書籍或文章),故提供一些看法做參考.

 

var在中文的翻譯叫推斷型別,也就是說var的真正型態是由編譯器來推斷,譬如底下程式

            var a = 0;//因為0為數值,所以編譯器推斷變數a的var真正資料型態為int

            var b = "aaa"; //因為"aaa"為字串所以推斷變數b的var真正資料型態為string

            a = "bbb"; //錯誤,因為上述已推論變數a為int故不能再變更資料型態

也就是說C#的var的其中一個特點就是C#的var與VB的variant是不同的東西,但因為名字很接近所以會讓用過VB的人產生誤會.(真正接近VB variant的是C# 4.0中的dynamic型態,未來再開一篇文章作介紹)

也就是說var依上面用途好像只是讓打字方便,實際上根本對程式沒太多影響,這就是目前濫用的最大因素.因為var的用途並不在於此.

 

之所以會有var的原因在於LINQ.

實際上var是為了讓LINQ處理一個問題所產生的產物.真正使用var的目的是為了解決這個問題,這個問題的由來如下

 

底下程式

    class Customer

    {

        public int Id { get; set; }

        public stringCustomerName { get; set; }

    }

 

    class Employee

    {

        public int Id { get; set; }

        public stringEmployeeName { get; set; }

        public Customer Customer { get; set; }

    }

 

 

    class Program

    {

        static void Main(string[] args)

        {

            List<Employee> emps = …; //取得相關Employee資料

            IEnumerable<?> r = from e in emps

            select e.EmployeeName, e.Customer.CustomerName

        }

程式希望最終取得的是EmployeeName與 CustomerName即可,但上面的select e.EmployeeName, e.Customer.CustomerName是無法通過編譯的,因為LINQ是一種強型別的查詢語言,所以傳回的資料型態無法確認.

故為了要解決這個問題,傳統的作法為新增一個傳回型別再把資料塞入如下

    class Result

    {

        public string CustomerName { get; set; }

        public string EmployeeName { get; set; }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            List<Employee> emps = …/

            IEnumerable<Result> r = from e in emps

                                    select new Result() { EmployeeName = e.EmployeeName, CustomerName = e.Customer.CustomerName };

        }

透過Result類別就能有資料型態來替代而解決了問題.

但這樣做會相當麻煩,因為如果每種查詢都要建立類似Result類別的模式,程式會很沒效率且有點呆.

故var出現了使用var後就可改成如下程式

            var r = from e in emps

                    select new { EmployeeName = e.EmployeeName, CustomerName = e.Customer.CustomerName };

 

編譯器遇到 這句程式碼就會自動產生的暫時性資料型態如同Result來儲存new { EmployeeName = e.EmployeeName, CustomerName = e.Customer.CustomerName };所指定的資料.而這就是新的匿名型別功能,所以編譯器產生了一個匿名型別可是卻產生了一個問題如何宣告一個變數型態來接收匿名型別的資料,而var剛好就是可以達成需求的做法.

所以在VS編譯滑鼠移至var變數時會出現IEnumerable<'a>的這種型態'a就是編譯器推斷後的暫時性資料型別.其中有兩個屬性EmployeeName與CustomerName

而這才是 var的真正用途所在