匿名型別、隱含型別與物件與集合初始設定與具名引數

 

一、隱含型別(Implicitly typed)

區域變數上的隱含型別(Implicitly typed local variables)

使用 var 關鍵字就可使用隱含型別宣告一個區域變數

例如:var price = 100;

隱含型別的限制與特性:

1、必須被宣告在區域變數裡,而不是靜態變數。

2、在宣告時必須給訂初值。

3、可透過函式回傳值給定初始值,但不可以是anonymous function

4、每行程式碼只能宣告一個隱含變數(var value1, value2=30;不允許)。

5、可宣告在陳述式裡面,例如:foreach、using、for

 

二、物件與集合初始設定

物件初始設定

 

person類別


namespace ConsoleApplication1
{
    class Person
    {
        public string name;
        public int age;

        //無參數建構子
        public Person()
        {

        }

        //一參數建構子
        public Person(string name)
        {
            this.name = name;
        }

        //二參數建構子
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
    }
}

主程式


using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //C#2.0作法
                Person Tom1 = new Person("Tom");
                Tom1.age = 1;

                Person Tom2 = new Person();
                Tom2.name = "Tom";
                Tom2.age = 1;

                //C#3.0作法
                Person Tom3 = new Person() { name = "Tom30", age = 30 };

                Person Tom4 = new Person { name = "Tom30", age = 30 };

                Person Tom5 = new Person("tom") {age = 30 };
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.ReadKey();
        }
    }
}

由C#2.0作法可得知,對物件的欄位或屬性或自動屬性設定初始值是由傳入參數建構子來做設定。

而由C#3.0作法可得知,對物件的欄位或屬性或自動屬性設定初始值是藉由大括號形式來作設定,

但是請記得必須要實作無參數建構子才可以。

 

承上,也可以使用陣列初始化

//陣列初始化
Person[] family = new Person[]
{
    new Person { name= "Tom", age= 1},
    new Person { name= "Jon", age= 2}
};

 

集合初始設定

//集合初始設定
//C#2.0做法
List<string> names = new List<string>();
names.Add("tom");
names.Add("jon");
names.Add("Mary");

//C#3.0做法
List<string> names2 = new List<string>()
{
    "tom","jon","Mary"
};

由例子可知,C#3.0作法使得程式變得更簡潔了

集合初始設定並沒局限於List型別,

只要有實作IEnumerable型別並有公開的Add方法即可。

 

三、陣列型式的隱含型別

static string MyFunction(string[] collection)
{
    string result = "";
    foreach (var item in collection)
    {
        result += item;
    }
    return result;
}

 

//這是一般陣列宣告的形式
string[] names3 = { "tom", "jon", "mary" };

//隱含型別陣列
//如果要將陣列傳入方法,可以告訴編譯器要傳入陣列的型別
var result = MyFunction(new string[] { "lo", "ve" });
//或者不需告訴編譯器要傳入陣列的型別,直接使用 new[] 也可
var result2 = MyFunction(new[] { "pie", "ce" });

 

//應用隱含宣告陣列來比較總花費
var familyArray = new[]
{
    new {Name="tom",Cost=4},
    new {Name="Jon",Cost=3}
};
int total = 0;
foreach (var item in familyArray)
{
    total = +item.Cost;
}

 

四、匿名型別

//使用匿名型別來建立物件
var anonyous = new { Name = "Tom", Age = 4 };
Console.WriteLine("{0} is {1} years old", anonyous.Name, anonyous.Age);

由上可知,想使用匿名型別就必須要使用 var 隱含宣告變數。

 

匿名型別的成員會包含

1.建構子

2.公開且唯獨的屬性

3.覆寫Equals、GetHashCode以及ToString方法

Equals方法主要是用來讓兩個不同的實體但擁有相同的匿名型別(屬性都一樣),

可以比較裡面每個屬性是否都相同。

GetHashCode方法,透過所有的屬性來產生雜湊碼,並會全部串接起來當作回傳值,

如果兩個相同的匿名型別就會產生相同的雜湊碼,反之則會不一樣。

另外注意一點的是,匿名型別只能是唯讀。

 

五、具名引數(Named Parameters or Named Arguments)

可與第二點的「物件與集合初始設定」做比較,這兩個形式很像很容易搞混。

先於Person類別新增一個具名引數測試方法

namespace ConsoleApplication1
{
    class Person
    {
        public string name;
        public int age;

        //無參數建構子
        public Person()
        {

        }

        //一參數建構子
        public Person(string name)
        {
            this.name = name;
        }

        //二參數建構子
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        //具名引數測試方法
        public void TestFunction(int age)
        {
            this.age = age;
        }

    }
}

實際操作

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Person PersonA = new Person("tomA") { };
            Console.WriteLine(PersonA.name);

            Person PersonB = new Person(name: "tomB") { };
            Console.WriteLine(PersonB.name);

            Person Person = new Person() { age = 3 };
            Console.WriteLine(Person.age);

            Person.TestFunction(5);
            Console.WriteLine(Person.age);

            Person.TestFunction(age: 10);
            Console.WriteLine(Person.age);

            Console.ReadKey();
        }
    }
}

以上範例 Person 的屬性 age 由於沒有實作建構子只能使用初始化來給值,

而 name 有實作,所以我們用 name 代替 age 說明也可以,

由範例我們可以知道經由物件初始設定 age=3,age 被指定為3,

而一般呼叫方法傳入參數的格式為 TestFunction(5),

但我們可以對方法使用具名引數 TestFunction(age: 10),

這時你會發現他們在給值的方式有點像,注意在在建構子與初始化設定上,

等於符號與冒號在此時可不能混用。