C#基礎教程之類class與結構struct的區別

一、類class

類class是引用類型,可以直接賦值為null,默認值也是null

XClass xClass = null;//語法正確

一般來說,某個類對象使用另一個類的對象賦值時,則兩者共用一個內存地址【節約內存空間】,ReferenceEquals引用比較此時返回true

            XClass xClass3 = new XClass() { Id = 7, Name = "天晴之海" };
            XClass xClass4 = xClass3;

類的構造函數(構造方法)

如果一個類沒有顯示定義構造函數,則默認有一個無參構造函數,

如果一個類已定義瞭帶參數的構造函數,如果不手動定義無參構造函數,則沒有無參構造函數

特殊類String:

特殊類【字符串String】雖然是引用類型,但對字符串的更新並不會修改字符串的原實際值,

字符串作為參數傳遞並不能篡改原來的值,

可以認為字符串雖然是引用類型,但使用時按值類型處理

二、結構struct

結構struct是值類型,不能直接賦值為null,結構的默認值為0,false,類型名稱字符串等

XStruct xStruct=null;//語法錯誤,不能為值類型賦值為null

如果想為值類型賦值為null,請使用可空類型Nullable<T>

public struct Nullable<T> where T : struct

比如如下代碼即可編譯通過:

Nullable<XStruct> xStruct = null;//可空值類型

或者簡化為

XStruct? xStruct = null;//可空值類型的簡化

    某個結構對象使用另一個結構的對象賦值時,則兩者的內存地址完全不同,第二個結構對象新開一個內存空間,隻不過內存的值完全一致【內存空間增加】,ReferenceEquals引用比較此時返回false

結構的構造函數

所有結構都自動繼承抽象值類型基類ValueType,有個默認無參構造函數ValueType(),因此無法在自定義結構中定義無參構造函數

using System.Runtime.InteropServices;
using System.Security;
 
namespace System
{
    //
    // 摘要:
    //     為值類型提供基類。
    [ComVisible(true)]
    public abstract class ValueType
    {
        //
        // 摘要:
        //     初始化 System.ValueType 類的新實例。
        protected ValueType();
 
        //
        // 摘要:
        //     指示此實例與指定對象是否相等。
        //
        // 參數:
        //   obj:
        //     要與當前實例進行比較的對象。
        //
        // 返回結果:
        //     如果 true 和該實例具有相同的類型並表示相同的值,則為 obj;否則為 false。
        [SecuritySafeCritical]
        public override bool Equals(object obj);
        //
        // 摘要:
        //     返回此實例的哈希代碼。
        //
        // 返回結果:
        //     一個 32 位帶符號整數,它是此實例的哈希代碼。
        [SecuritySafeCritical]
        public override int GetHashCode();
        //
        // 摘要:
        //     返回此實例的完全限定類型名稱。
        //
        // 返回結果:
        //     完全限定的類型名稱
        public override string ToString();
    }
}

值類型重寫瞭Equals方法,如果一個值類型的具體屬性值完全一致時,兩個對象是相等的

三、測試控制臺應用程序GenericTemplateDemo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace GenericTemplateDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.SetWindowSize(120, 30);
            Console.WriteLine($"結構的默認值為類型名(一定不為null):{default(XStruct)},類型名為【{typeof(XStruct)}】");
            Console.WriteLine($"類的默認值為null?【{default(XClass) == null}】");
            Console.WriteLine("---------------------------------結構的Equal比較---------------------------------");
            XStruct xStruct1 = new XStruct() { Id = 5, Name = "ABC" };
            XStruct xStruct2 = new XStruct("ABC") { Id = 5 };
            Console.WriteLine($"結構一的內容{{Id:{xStruct1.Id},Name:{xStruct1.Name}}}");
            Console.WriteLine($"結構二的內容{{Id:{xStruct2.Id},Name:{xStruct2.Name}}}");
            Console.WriteLine();
            Console.WriteLine($"比較兩個結構的實例值是否相等:{xStruct1.Equals(xStruct2)}");
            Console.WriteLine($"比較兩個結構的引用是否指向同一個實例:{ReferenceEquals(xStruct1, xStruct2)}");
 
            XStruct xStruct3 = new XStruct("修吾") { Id = 8 };
            XStruct xStruct4 = xStruct3;
            Console.WriteLine($"結構三的內容{{Id:{xStruct3.Id},Name:{xStruct3.Name}}}");
            Console.WriteLine($"結構四的內容{{Id:{xStruct4.Id},Name:{xStruct4.Name}}}");
            Console.WriteLine();
            Console.WriteLine($"比較兩個結構的實例值是否相等:{xStruct3.Equals(xStruct4)}");
            Console.WriteLine($"比較兩個結構的引用是否指向同一個實例:{ReferenceEquals(xStruct3, xStruct4)}");
            Console.WriteLine("---------------------------------類的Equal比較---------------------------------");
            XClass xClass1 = new XClass() { Id = 6, Name = "毒瘴泉" };
            XClass xClass2 = new XClass("毒瘴泉") { Id = 6 };
            Console.WriteLine($"類一的內容{{Id:{xClass1.Id},Name:{xClass1.Name}}}");
            Console.WriteLine($"類二的內容{{Id:{xClass2.Id},Name:{xClass2.Name}}}");
            Console.WriteLine();
            Console.WriteLine($"比較兩個類的實例值是否相等:{xClass1.Equals(xClass2)}");
            Console.WriteLine($"比較兩個類的引用是否指向同一個實例:{ReferenceEquals(xClass1, xClass2)}");
            Console.WriteLine();
            XClass xClass3 = new XClass() { Id = 7, Name = "天晴之海" };
            XClass xClass4 = xClass3;
            Console.WriteLine($"類三的內容{{Id:{xClass3.Id},Name:{xClass3.Name}}}");
            Console.WriteLine($"類四的內容{{Id:{xClass4.Id},Name:{xClass4.Name}}}");
            Console.WriteLine();
            Console.WriteLine($"比較兩個類的實例值是否相等:{xClass3.Equals(xClass4)}");
            Console.WriteLine($"比較兩個類的引用是否指向同一個實例:{ReferenceEquals(xClass3, xClass4)}");
            Console.ReadLine();
        }        
    }
 
    /// <summary>
    /// 測試用的結構,結構繼承ValueType,而ValueType重寫瞭Equals(object obj)方法,因此比較
    /// 結構不允許顯式定義無參的構造函數,因 結構struct一經定義,自動會生成一個無參構造函數
    /// </summary>
    struct XStruct
    {
        public XStruct(string name)
        {
            Id = 0;
            Name = name;
        }
        public int Id { get; set; }
        public string Name { get; set; }
    }
 
    /// <summary>
    /// 測試用的類
    /// </summary>
    class XClass
    {
        public XClass()
        {
        }
        public XClass(string name)
        {
            Id = 0;
            Name = name;
        }
        public int Id { get; set; }
        public string Name { get; set; }
    }
}

四、程序運行如圖:

補充:結構與類的區別

1.類和結構有以下幾個基本的不同點:

  • 類是引用類型,結構是值類型。
  • 結構不支持繼承。
  • 結構不能聲明默認的構造函數。
  • 結構體中聲明的字段無法賦予初值,類可以
  • 類的對象是存儲在堆空間中,結構存儲在棧中。

2.選擇使用情況

堆空間大,但訪問速度較慢,棧空間小,訪問速度相對更快。當我們描述一個輕量級對象的時候,結構可提高效率,成本更低。不過假如我們在傳值的時候希望傳遞的是對象的引用地址而不是對象的拷貝,就應該使用類瞭。

總結

到此這篇關於C#基礎教程之類class與結構struct區別的文章就介紹到這瞭,更多相關C# 類class與結構struct區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: