1. 程式人生 > >C# in Depth學習筆記-從簡單的資料型別開始

C# in Depth學習筆記-從簡單的資料型別開始

C# 1中定義的產品型別

以定義一個表示產品的型別作為開始,然後進行處理。

其中Product 型別內部封裝了幾個屬性。同時還要建立預定義產品的一個列表。

//程式碼清單1-1
public class Product
{
    string name;
    public string Name { get { return name; } }
    decimal price;
    public decimal Price { get { return price; } }
    public Product(string name,decimal price)
    {
        
this.name = name; this.price = price; } public static ArrayList GetSampleProducts() { ArrayList list = new ArrayList(); list.Add(new Product("A", 1.99m)); list.Add(new Product("B", 2.99m)); list.Add(new Product("C", 3.99m)); list.Add(new Product("
D", 4.99m)); return list; } }

以上C# 1程式碼存在如下3個侷限:

①ArrayList 沒有提供與其內部內容有關的編譯時資訊。不慎在 GetSampleProducts 建立的列表中新增一個字串是完全有可能的,而編譯器對此沒有任何反應。

②程式碼中為屬性提供了公共的取值方法,這意味著如果新增對應的賦值方法,那麼賦值方法也必須是公共的。

③用於建立屬性和變數的程式碼很複雜——封裝一個字串和一個十進位制數應該是一個十分簡單的任務,不該這麼複雜。

來看看C# 2作了哪些改進。


C# 2中的強型別集合

我們所做的第一組改動,針對上面列出的前兩項,包含C# 2中最重要的改變:泛型。

//程式碼清單1-2
public class Product
{
    string name;
    public string Name
    {
        get { return name; }
        private set { name = value; }
    }
    decimal price;
    public decimal Price
    {
        get { return price; }
        private set { price = value; }
    }
    public Product(string name,decimal price)
    {
        Name = name;
        Price = price;
    }
    public static List<Product> GetSampleProducts()
    {
        List<Product> list = new List<Product>();
        list.Add(new Product("A", 1.99m));
        list.Add(new Product("B", 2.99m));
        list.Add(new Product("C", 3.99m));
        list.Add(new Product("D", 4.99m));
        return list;
    }
    public override string ToString()
    {
        return string.Format("{0}:{1}", name, price);
    }
}

現在屬性擁有了私有的賦值方法(我們在建構函式中使用了這兩個賦值方法)。

並且它能非常“聰明”地猜出 List<Product> 是告知編譯器列表中只能包含 Product 。

試圖將一個不同的型別新增到列表中,會造成編譯時錯誤,並且當你從列表中獲取結果時,也並不需要轉換結果的型別。

C# 2解決了原先的3個問題中的2個。下面展示了展示了C# 3如何解決剩下的那個問題。


C# 3中自動實現的屬性

自動實現的屬性和簡化的初始化,相比Lambda表示式等特性來說,有點微不足道,不過它們可以大大地簡化程式碼。

//程式碼清單1-3
public class Product
{
    public string Name { get; private set; }
    public decimal Price { get; private set; }
    Product() { }
    public static List<Product> GetSampleProducts()
    {
        return new List<Product>()
        {
            new Product{Name="A", Price=1.99m},
            new Product{Name="B", Price=2.99m},
            new Product{Name="C", Price=3.99m},
            new Product{Name="D", Price=4.99m}
        };
    }
    public override string ToString()
    {
        return string.Format("{0}:{1}", Name, Price);
    }
}

不再有任何程式碼、可見的變數與屬性關聯,而且硬編碼的列表是以一種全然不同的方式構建的。

由於沒有 name 和 price 變數可供訪問,我們必須在類中處處使用屬性,這增強了一致性。

現在有一個私有的無參建構函式,用於新的基於屬性的初始化。(設定這些屬性之前,會對每一項呼叫這個建構函式。)

在本例中,實際上可以完全刪除舊的公共建構函式。但這樣一來,外部程式碼就不能再建立其他的產品例項了。


C# 4中的命名實參

對於C# 4,涉及屬性和建構函式時,我們需要回到原始程式碼。

其中有一個原因是為了讓它不易變:儘管擁有私有賦值方法的型別不能被公共地改變,但如果它也不能被私有地改變,將會顯得更加清晰。

不幸的是,對於只讀屬性,沒有快捷方式,但C# 4允許我們在呼叫建構函式時指定實參的名稱,

如下所示,它為我們提供了和C# 3的初始化程式一樣的清晰度,而且還移除了易變性(mutability)。

//程式碼清單1-4
public class Product
    {
        readonly string name;
        public string Name { get { return name; } }
        readonly decimal price;
        public decimal Price { get { return price; } }
        public Product(string name,decimal price)
        {
            this.name = name;
            this.price = price;
        }
        public static List<Product> GetSampleProducts()
        {
            return new List<Product>()
            {
                new Product(name:"A", price:1.99m),
                new Product(name:"B", price:2.99m),
                new Product(name:"C", price:3.99m),
                new Product(name:"D", price:4.99m)
            };
        }
        public override string ToString()
        {
            return string.Format("{0}:{1}", Name, Price);
        }
    }

在這個特定的示例中,該特性的好處不是很明顯,但當方法或建構函式包含多個引數時,它可以使程式碼的含義更加清楚——特別是當引數型別相同,或某個引數為 null 時。

當然,你可以選擇什麼時候使用該特性,只在使程式碼更好理解時才指定引數的名稱。

圖1-1總結了 Product 型別的演變歷程。注意,圖中沒有涉及C# 5。這是因為C# 5主要特性(非同步函式)面向的領域還沒有太多的語言支援。稍後,我們將簡單看一下。

 

到目前為止,你看到的變化幅度都不大。事實上,泛型的加入( List<Product> 語法)或許是C# 2最重要的一個部分。

但是,我們現在只看到了它的部分用處。雖然沒有什麼讓人心跳加快的東西,但我們只是剛剛開始。下一個任務是以字母順序列印產品列表。