C#圖解教程 第十章 結構


結構

什么是結構


結構是程序員定義的數據類型,與類非常相似。它們有數據成員和函數成員。結構與類的重要區別是:

  • 類是引用類型而結構是值類型
  • 結構是隱式密封的,這意味着它們不能被派生

聲明結構的語法與聲明類相似

關鍵字
  ↓
struct SturctName
{
    MemberDeclarations
}

例:Point結構

struct Point
{
    public int X;
    public int Y;
}
class Program
{
    static void Main()
    {
        Point first,second,third;
        first.X=10;first.Y=10;
        second.X=20;second.Y=20;
        third.X=first.X+second.X;
        third.Y=first.Y+second.Y;
        Console.WriteLine("first:  {0},{1}",first.X,first.Y);
        Console.WriteLine("second:  {0},{1}",second.X,second.Y);
        Console.WriteLine("third:  {0},{1}",third.X,third.Y);
    }
}

結構是值類型


和所有值類型一樣,結構類型變量含有自己的數據。因此:

  • 結構類型變量不能為null
  • 兩個結構變量不能引用同一對象

例:結構變量的內存安排

class CSimple
{
    public int X;
    public int Y;
}
struct Simple
{
    public int X;
    public int Y;
}
class Program
{
    static void Main()
    {
        var cs=new CSimple();
        var ss=new Simple();
        ...
    }
}

對結構賦值


把一個結構賦值給另一個結構,就將一個結構的值復制給另一個結構。這和復制類變量不同,復制類變量時只復制引用。
例:結構變量賦值與類變量賦值的區別

class CSimple
{
    public int X;
    public int Y;
}
struct Simple
{
    public int X;
    public int Y;
}
class Program
{
    static void Main()
    {
        CSimple cs1=new CSimple(),cs2=null;
        Simple ss1=new Simple(),ss2=new Simple();
        cs1.X=ss1.X=5;
        cs1.Y=ss1.Y=10;
        cs2=cs1;
        ss2=ss1;
    }
}

構造函數和析構函數


結構可以有實例構造函數和靜態構造函數,但不允許有析構函數。

實例構造函數

語言隱式地為每個結構提供一個無參構造函數。這個構造函數把結構的每個成員設置為該類型的默認值。值成員設置成它們的默認值,引用成員設置為null。
例:帶參數的構造函數

struct Simple
{
    public int X;
    public int Y;
    public Simple(int a,int b)
    {
        X=a;
        Y=b;
    }
}
class Program
{
    static void Main()
    {
        var s1=new Simple();
        var s2=new Simple(4,10);
        Console.WriteLine("{0},{1}",s1.X,s1.Y);
        Console.WriteLine("{0},{1}",s2.X,s2.Y);
    }
}

也可以不是用new運算符創建結構實例,然而這樣做,有一些限制:

  • 在顯式設置數據成員后,才能使用它們的值
  • 在對所有數據成員賦值后,才能調用任何函數成員

例:不用new創建結構實例

struct Simple
{
    public int X;
    public int Y;
}
class Program
{
    static void Main()
    {
        Simple s1,s2;
        Console.WriteLine("{0},{1}",s1.X,s1.Y);  //編譯錯誤
                                     ↑     ↑
                                      還未賦值
        s2.X=5;
        s2.Y=10;
        Console.WriteLine("{0},{1}",s2.X,s2.Y);  //沒錯誤
    }
}
靜態構造函數

與類相似,結構的靜態構造函數創建並初始化靜態數據成員,而且不能引用實例成員。
以下兩種行為發生前,會調用靜態構造函數

  • 調用顯式聲明的構造函數
  • 引用結構的靜態成員
構造函數和析構函數小結

字段初始化語句是不允許的


在結構中字段初始化語句是不允許的。

struct Simple
{
    public int x=10;  //編譯錯誤
    public int y=10;  //編譯錯誤
}

結構是密封的


結構總是隱式密封的,因此,不能從它們派生其他結構。
結構不支持繼承,所以下列修飾符不能用於結構聲明:

  • protected
  • internal
  • abstract
  • virtual

結構都派生自System.ValueType,System.ValueType派生自object。
兩個可以用於結構成員並與繼承相關的關鍵字是new和override,當創建一個和基類System.ValueType的成員有相同名稱的成員時使用它們。

裝箱和拆箱


如同其他值類型數據,如果想將一個結構實例作為引用類型對象,必須創建裝箱(boxing)副本。裝箱的過程就是制作值類型變量的引用類型副本。裝箱和拆箱(unboxing)在第16章詳述。
6個重要的.NET概念: - 堆棧,堆,值類型,引用類型,裝箱和拆箱

結構作為返回值和參數


結構可以作為返回值和參數

  • 返回值 當結構作為返回值時,將創建它的副本並從函數成員返回
  • 值參數 當結構作為值參數時,將創建實參結構的副本。該副本用於方法的執行中
  • ref和out參數 若把一個結構用作ref或out參數,傳入方法的是結構的引用,這樣就可以修改其數據成員

關於結構的其他信息


對於結構進行分配比創建類的實例開銷小,所以使用結構替代類有時可以提高性能,但要注意到裝箱和拆箱的高代價。
關於結構,需要知道的最后一些事情如下:

  • 預定義簡單類型(int、short、long等等),盡管在.NET和C#中被視為原始類型,它們實際上在.NET中都實現為結構
  • 可以使用與聲明分部類相同的方法聲明分部結構,如第6章所述。

結構和類一樣,可以實現接口。接口將在第15章闡述。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM