[C#] 結構

  • 15602
  • 0
  • 2009-12-12

摘要:[C#]結構

Interduction

我們很常用 class 來做事,可是卻忘了 struct 的存在,結構由於被設計成為實值型別,所以在效率上的表現要比類別來的出色,

如只提供儲存數值資料功能,使用類別就顯得浪費了。結構也可以建立各種成員,例如建構式、常數、欄位、方法、屬性、索引子、運算子、事件和巢狀型別等等,若要弄得這麼複雜,將失去使用結構型別的意義。結構很有彈性,建立結構物件可以不需要使用 new 關鍵字,他有專屬的預設建構式;當然你也可以自己打造建構式,而建立物件的時候必須透過 new 關鍵字,引用此建構式。

 

Reference

              HOW TO:在結構之間實作使用者定義的轉換 (C# 程式設計手冊

 

與類別比較

  • 結構宣告內不能初始化欄位,除非將其宣告為 const 或 static。

  • 結構不可宣告預設建構函式 (沒有參數的建構函式) 或解構函式。

  • 結構無法繼承自類別或其他結構。

  • 結構是在指派時複製的。當指派結構給新變數時,就會複製所有資料,而新變數所做的任何修改都不會變更原始複本的資料。

  • 結構為實值型別,而類別則是參考型別。

  • 與類別不同的是,結構不需使用 new 運算子就能執行個體化

  • 結構可以宣告含有參數的建構函式。

  • 結構無法從另一個結構或類別繼承而來,且它不能成為類別的基底。所有結構都是從繼承自 System.ObjectSystem.ValueType 直接繼承而來

  • 結構可實作介面

  • 結構可以用來當做可為 Null 的型別,而且可以對其指派 null 值。

 

Example

using System;
 
class UsingStruct
{
    static void Main(string[] args)
    {
        ClassStruct theClassStruct;
        theClassStruct.student = "三小俠";
        theClassStruct.stuNumber = "20051212001";
        Console.WriteLine(
            "學生:" + theClassStruct.student + "\t" + 
            "學號:" + theClassStruct.stuNumber
            ); 
 
 
        ClassStruct theClassStruct1 = new ClassStruct("馬小九", "20010105002");
        Console.WriteLine(
            "學生:" + theClassStruct1.student + "\t" + 
            "學號:" + theClassStruct1.stuNumber 
            );
        Console.ReadLine(); 
    }
}
public struct ClassStruct
{
    public string student;
    public string stuNumber;
 
    public ClassStruct(string student, string stuNumber)
    {
        this.student = student;
        this.stuNumber = stuNumber; 
    }
}

執行結果:

學生:三小俠       學號:20051212001

學生:馬小九       學號:20010105002

 

注意事項:

結構無法繼承自類別或其他結構 ,可是,結構卻可以實做介面

所以在結構裡面不可使用,protected 與 internal protected 存取修飾子;若是實做介面,也是使用 public 修飾子。

以下是測試:

namespace dog {
    internal struct TestStruct {
        private string _Name;
        private int _Number;
        private float _Price;
        private double _Water;

        internal float Price {
            get { return _Price; }
            set { _Price = value; }
        }
        
        
        internal string GetName() {
            return _Name;
        }
        
        //這邊編譯錯誤
        protected int GetNumber() {
            return _Number;
        }
        
        //這邊編譯錯誤
        internal protected double GetWater(){
            return _Water;
        }
    }
}

 

補充 :

1。結構繼承介面

先定義一個介面

namespace ClassLibrary1 {
    internal interface Interface1 {
        string MethodB();
    }
}

 

再來定義一個結構並且繼承介面

namespace ClassLibrary1 {
    public struct ClassStructTest : Interface1{
        public string MethodB() {
            return "MethodB";
        }
    }
}

 

Client 端程式碼

class Program {
        static void Main(string[] args) {
            //建立結構物件
            ClassLibrary1.ClassStructTest oStruct = new ClassLibrary1.ClassStructTest();                                    
            Console.WriteLine(oStruct.MethodB());            

            Console.ReadKey();
        }
    }

 

輸出結果

延伸閱讀

[C#]Effective C# 條款六: 明辨值類型與參考類型的使用場合 - Level Up- 點部落

[C#]Effective C# 條款七: 將值類型盡可能實現為具有常量性與原子性的類型 - Level Up- 點部落

 

原文參考呂文達研究室

三小俠  小弟獻醜,歡迎指教