C#個人總結,第三章:對象和類型

1. 類和結構

(1)類和結構實際上都是創建對象的模板,每個對象都包含數據,並提供了處理和訪問數據的方法。

(2)類定義了類的每個對象(稱爲實例)可以包含什麼數據和功能。

(3)結構與類的區別是它們在內存中的存儲方式、訪問方式(類是存儲在堆(heap)上的引用類型,而結構是存儲在棧(stack)上的值類型)和它們的一些特徵(如結構不支持繼承。

(4)結構struct,類Class

2. 類

(1)類中的數據和函數稱爲類的成員。成員的可訪問性可以是public、protected、internal protected、private或internal

2.1 數據成員

(1)數據成員是包含類的數據——字段、常量和事件的成員。數據成員可以是靜態數據。類成員總是實例成員,除非用static進行顯式的聲明。

2.2 函數成員

(1)函數成員提供了操作類中數據的某些功能,包括方法、屬性、構造函數和終結器(finalizer)、運算符以及索引器。

2.2.1 方法

(1)方法的聲明

(2)調用方法:代碼:

namespace study3_2_2_1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Pi is " + MathTest.GetPi());
            int x = MathTest.GetSquareOf(5);
            Console.WriteLine("Square of 5 is " + x);

            MathTest math = new MathTest();

            math.value = 30;
            Console.WriteLine("Value field of math variable contains " + math.value);
            Console.WriteLine("Square of 30 is " + math.GetSquare());
        }
    }

    class MathTest
    {
        public int value;

        public int GetSquare()
        {
            return value * value;
        }

        public static int GetSquareOf(int x)
        {
            return x * x;
        }

        public static double GetPi()
        {
            return 3.14159;
        }
    }
}

結果:

(3)給方法傳遞參數:int通過值傳遞給方法,對應方法對該int的值所做的任何改變都沒有改變原int對象的值。但如果把數組或其他引用類型(如類)傳遞給方法,對應的方法就會使用該引用改變這個數組中的值,而新值會反射在原始數組對象上。

代碼:

namespace study3_2_2_5
{
    class Program
    {
        static void SomeFunction(int[] ints, int i)
        {
            ints[0] = 100;
            i = 100;
        }
        static void Main(string[] args)
        {
            int i = 0;
            int[] ints = { 0,1,2,4,8};

            Console.WriteLine("i = " + i);
            Console.WriteLine("ints[0] = " + ints[0]);
            Console.WriteLine("Calling SomeFunction.");

            SomeFunction(ints, i);

            Console.WriteLine("i = " + i);
            Console.WriteLine("ints[0] = " + ints[0]);
        }
    }
}

結果:


(4)ref參數:迫使值參數通過引用傳送給方法。

(5)out參數:傳遞給該方法的變量可以不初始化。

(6)命名參數:參數一般需要按定義的順序傳送給方法。命名參數允許按任意順序傳遞。

(7)可選參數:參數也可以是可選的。必須爲可選參數提供默認值。可選參數還必須是方法定義的最後一個參數。

(8)方法的重載:方法的幾個版本有不同的簽名(即:方法名相同,但參數的個數(和/或)類型不同)。限制:兩個方法不能僅在返回類型上有區別; 兩個方法不能僅根據參數是聲明爲ref還是out來區分。

2.2.2 屬性:屬性(property)的概念是:它是一個方法或一對方法,在客戶端代碼看來,它(們)是一個字段。

(1)只讀和只寫屬性:在屬性定義中省略set訪問器,就可以創建只讀屬性。同樣,在屬性定義中省略get訪問器,就可以創建只寫屬性。

(2)屬性的訪問修飾符:屬性可以有公有的get訪問器和私有或受保護的set訪問器。

(3)自動實現的屬性:

(4)內聯:

2.2.3 構造函數:

(1)聲明基本構造函數的語法就是聲明一個與包含的類同名的方法,但該方法沒有返回類型。

(2)構造函數的重載遵循與其他方法相同的規則。

(3)如果提供了帶參數的構造函數,編譯器就不會自動提供默認的構造函數。只有在沒有定義任何構造函數時,編譯器纔會自動提供默認的構造函數

2.2.3.1 靜態構造函數:

(1)C#的一個新特徵是也可以給類編寫無參數的靜態構造函數。這種構造函數只執行一次,而前面的構造函數是實例構造函數,只要創建類的對象,就會執行它。

(2)編寫靜態構造函數的一個原因是,類有一些靜態字段或屬性,需要在第一次使用類之前,從外部源中初始化這些靜態字段和屬性。

(3)注意,無參數的實例構造函數與靜態構造函數可以在同一個類中同時定義。

(4)代碼:

namespace study3_2_2_3
{
    public class UserPreferences
    {
        public static readonly Color BackColor;

        static UserPreferences()
        {
            DateTime now = DateTime.Now;
            if (now.DayOfWeek == DayOfWeek.Thursday || now.DayOfWeek == DayOfWeek.Wednesday)
            {
                BackColor = Color.Green;
            }
            else
            {
                BackColor = Color.Red;
            }
        }

        private UserPreferences()
        {

        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("User-preferences:BackColor is: " +
                UserPreferences.BackColor.ToString());
        }
    }
}

(5)結果:

2.2.3.2 從構造函數中調用其他構造函數

(1)C#有一個特殊的語法,稱爲構造函數初始化器。



(2)這裏this關鍵字僅調用參數最匹配的那個構造函數。注意,構造函數初始化器在構造函數的函數體之前執行。

2.3 只讀字段

(1)readonly關鍵字比const靈活得多,允許把一個字段設置爲常量,但還需要執行一些計算,以確定它的初始值。

(2)其規則是可以在構造函數中給只讀字段賦值,但不能在其他地方賦值。只讀字段還可以是一個實例字段,而不是靜態字段,類的每個實例可以有不同的值。與const字段不同,如果要把只讀字段設置爲靜態,就必須顯式聲明它。

3. 匿名類型

(1)var關鍵字,用於表示隱式類型化的變量。var與new關鍵字一起使用時,可以創建匿名類型。匿名類型只是一個繼承自Object 且沒有名稱的類。該類的定義從初始化器中推斷,類似於隱式類型化的變量。

(2)var captain = new (FirstName = "James", MiddleName = "T", LastName = "Kirk");

4. 結構

(1)有時僅需要一個小的數據結構。此時,類提供的功能多於我們需要的功能,由於性能原因,最好使用結構。

(2)爲結構定義函數與爲類定義函數完全相同

(3)結構是值類型,不是引用類型。它們存儲在棧中或存儲爲內聯。

(4)結構不支持繼承;對於結構構造函數的工作方式有一些區別。尤其是編譯器總是提供一個無參數的默認構造函數,它是不允許替換的;使用結構,可以指定字段如何在內存中的佈局。

4.1 結構是值類型

(1)雖然結構是值類型,但在語法上常常可以把它們當作類來處理。

(2)因爲結構是值類型,所以New運算符與類和其他引用類型的工作方式不同。New運算符並不分配堆中的內存,而是隻調用相應的構造函數,根據傳送給它的參數,初始化所有的字段。對於結構,變量聲明實際上是爲整個結構在棧中分配空間,所以就可以爲它賦值了。

(3)結構遵循其他數據類型都遵循的規則:在使用前所有的元素都必須進行初始化。在結構上調用new運算符,或者給所有的字段分別賦值,結構就完全初始化了。當然,如果結構定義爲類的成員字段,在初始化包含的對象時,該結構會自動初始化爲0。

(4)結構主要用於小的數據結構。但當把結構作爲參數傳遞給方法時,應把它作爲ref參數傳遞,以避免性能損失——此時只傳遞了結構在內存中的地址,這樣傳遞速度就與在類中的傳遞速度工樣快了。但如果這樣做,就必須注意被調用的方法可以改變結構的值。

4.2 結構和繼承

(1)結構不支持繼承。

4.3 結構的構造函數

(1)爲結構定義構造函數的方式與爲類定義構造函數的方式相同,但不允許定義無參數的構造函數。

5. 部分類

(1)partial關鍵字允許把類、結構或接口放在多個文件中。編譯時,只會生成一個類,而類中有各個文件中的方法。

6. 靜態類

(1)如果類只包含靜態的方法和屬性,該類就是靜態的。靜態類在功能上與使用私有靜態構造函數創建的類相同。不能創建靜態類的實例。使用static關鍵字。

7. Object類

7.1 System.Object()方法

  • ToString()
  • GetHashtable()
  • Equals()和ReferenceEquals()
  • Finalize()
  • GetType()
  • MemberwiseClone()

7.2 ToString()

(1)代碼:

namespace study3_7_2
{
    class Program
    {
        static void Main(string[] args)
        {
            Money cash1 = new Money();
            cash1.Amount = 40M;
            Console.WriteLine("cash1.ToString() returns:" + cash1.ToString());
            Console.ReadLine();
        }
    }

    public class Money
    {
        private decimal amount;

        public decimal Amount
        {
            get { return amount; }
            set { amount = value; }
        }

        public override string ToString()
        {
            return "$"+Amount.ToString();
        }
    }
}

(2)結果:

8. 擴展方法

(1)擴展方法,允許改變一個類,但不需要該類的源代碼。擴展方法是靜態方法。

(2)對於擴展方法,第一個參數是要擴展的類型,它放在this關鍵字的後面。這告訴編譯器,這個方法是Money類型的一部分。

(3)在主程序中,擴展方法看起來像是另一個方法。它沒有顯示第一個參數,也不能對它進行任何處理。如:

public statio class MoneyExtension
{
public static void AddToAmount(this MOney money, decimal amountToAdd)
{
money.Amount += amountToAdd;
}
}

主:cash1.AddToAmount(10M);











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章