淺析C#中的結構體和類


類和結構是 .NET Framework 中的常規類型系統的兩種基本構造。 兩者在本質上都屬於數據結構。封裝着一組總體作為一個邏輯單位的數據和行為。 數據和行為是該類或結構的“成員”,它們包括各自的方法、屬性和事件等

對於C/C++程序員來說。結構體和類的差別非常小。僅僅是結構體的默認成員變量為public,類的默認成員變量為private。

可是對於C#來說,結構體和類有非常多的不同。

首先來談一談為何須要結構體:
最主要的原因就是結構體有能力去管理、使用不同數據類型的組合。

.NET支持值類型和引用類型的概念,全部的C#內置類型中,除了string外均為值類型。

在C#中,結構體是值類型。類是引用類型。

值類型能夠降低對堆的管理、使用。降低垃圾回收,表現出更好的性能。可是值類型也有不好的一面。比方會涉及到裝箱拆箱等操作。

以下定義一個結構體:

public struct Foo
{
    // Fields
    private string fooString;
    private int fooNumber;
    // Property
    public string FooString
    {
        get
        {
            return fooString;
        }
        set
        {
            fooString = value;
        }
    }
    // Method
    public int GetFooNumber()
    {
        return fooNumber;
    }
}

能夠看到。結構體和類非常的類似。讓我們更深層次的看看兩者的不同。


1繼承
結構體繼承自System.ValueType,而類繼承自System.Object。結構體不能繼承其它的類或結構體,可是能夠把結構體當做是接口。因為接口僅僅是用於引用類型的操作,所以把結構體當成接口就會隱式的發生裝箱操作。

比如例如以下代碼:
struct Foo : IFoo
{
int x;
}
IFoo iFoo = new Foo();

2構造
C#不同意結構體具有無參數的默認構造函數。原因是:對於值類型,編譯器既不會生成默認構造函數。也不會調用默認構造函數。所以你不能這樣初始化:

struct MyWrongFoo
{
    int x = 1;
}

可是你能夠使用new:
Foo foo = new Foo();
這里須要注意的是,雖然使用了new操作,可是結構體分配在棧上,而不是堆上。更有趣的是,new操作沒有調用無參數的構造函數。

看看以下的代碼:

struct Foo
{
    int x;
    public Foo(int x)
    {
        this.x = x;
    }
}
class FooTester
{
    [STAThread]
    static void Main(string[] args)
    {
        Foo f = new Foo();
    }
}

這里我重載了構造函數。就能夠使用new了。


所以我們能夠這樣:
調用 new Foo()
調用重載的構造函數初始化
顯示的設置每一個值:
Foo foo;
foo.x = 0;

3析構
我們不能為結構體定義析構函數。

4僅僅讀關鍵字
對於引用類型。readonly關鍵字阻止你將引用指到其它對象,可是無法阻止你改變該對象的狀體。
對於值類型來說。readonly關鍵字與C++中的const非常像。阻止你改變對象的狀態。

class MyReferenceType
{
    int state;
    public int State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
        }
    }
}
struct MyValueType
{
    int state;
    public int State
    {
        get
        {
            return state;
        }
        set
        {
            state = value;
        }
}
    }
class Program
{
    readonly MyReferenceType myReferenceType = new MyReferenceType();
    readonly MyValueType myValueType = new MyValueType();
    public void SomeMethod()
    {
        myReferenceType = new MyReferenceType(); // Compiler Error
        myReferenceType.State = 1234; // Ok
        myValueType = new MyValueType(); // Compiler Error
        myValueType.State = 1234; // Compiler Error
    }
}

總結:
為結構定義默認(無參數)構造函數是錯誤的。

在結構體中初始化實例字段也是錯誤的。

僅僅能通過兩種方式初始化結構成員:一是使用參數化構造函數,二是在聲明結構后分別訪問成員。 對於不論什么私有成員或以其它方式設置為不可訪問的成員,僅僅能在構造函數中進行初始化。

假設使用 new 運算符創建結構對象。則會創建該結構對象。並調用適當的構造函數。

與類不同,結構的實例化能夠不使用 new 運算符。

在此情況下不存在構造函數調用。因而能夠提高分配效率。 可是,在初始化全部字段之前,字段將保持未賦值狀態且對象不可用。

當結構包括引用類型作為成員時,必須顯式調用該成員的默認構造函數,否則該成員將保持未賦值狀態且該結構不可用。 (這將導致編譯器錯誤 CS0171。)

對於結構。不像類那樣存在繼承。 一個結構不能從還有一個結構或類繼承。並且不能作為一個類的基。 可是,結構從基類 Object 繼承。

結構可實現接口。其方式同類全然一樣。


免責聲明!

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



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