簡體   English   中英

你能在一個結構中有一個類嗎?

[英]Can you have a class in a struct?

在C#中是否可以使用具有類型類型的成員變量的Struct? 如果是這樣,信息存儲在哪里,堆棧,堆,或兩者?

是的你可以。 指向類成員變量 的指針 與結構的其余值一起存儲 在堆棧中 ,類實例的數據存儲在堆上。

結構也可以包含類定義作為成員(內部類)。

這是一些真正無用的代碼,至少編譯並運行以顯示它是可能的:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MyStr m = new MyStr();
            m.Foo();

            MyStr.MyStrInner mi = new MyStr.MyStrInner();
            mi.Bar();

            Console.ReadLine();
        }
    }

    public class Myclass
    {
        public int a;
    }

    struct MyStr
    {
        Myclass mc;

        public void Foo()
        {
            mc = new Myclass();
            mc.a = 1;
        }

        public class MyStrInner
        {
            string x = "abc";

            public string Bar()
            {
                return x;
            }
        }
    }
}

類內容存儲在堆上。

對類的引用(與指針幾乎相同)與struct內容一起存儲。 存儲結構內容的位置取決於它是局部變量,方法參數還是類的成員,以及它是否被閉包裝箱或捕獲。

of a class object or else a null referece. 如果結構的某個字段是類類型,則該字段將保留類對象的 ,或者保留null引用。 如果所討論的類對象是不可變的(例如string ),則存儲其標識也將有效地存儲其內容。 . 但是,如果所討論的類對象是可變的,那么存儲該標識將是一種有效的存儲內容的方法,

通常,應避免在結構中存儲可變類類型,除非以下兩種情況之一適用:

  1. 事實上,人們感興趣的是類對象的身份而不是其內容。 例如,可以定義一個`FormerControlBounds`結構,它保存“Control”和“Rectangle”類型的字段,並表示某個時刻控件具有的“Bounds”,以便以后能夠恢復控件到它早先的位置。 “Control”字段的目的不是保存控件狀態的副本,而是識別應該恢復其位置的控件。 通常,struct應該避免訪問它擁有引用的對象的任何可變成員,除非很明顯這樣的訪問是指有關對象的當前可變狀態(例如在`CaptureControlPosition`或` RestoreControlToCapturedPosition`方法,或`ControlHasMoved`屬性)。
  2. 該字段是`private`,唯一讀取它的方法是為了檢查其屬性而不將對象本身暴露給外部代碼,並且編寫它的唯一方法將創建一個新對象,執行所有突變它將永遠發生在它上面,然后存儲對該對象的引用。 例如,人們可以設計一個`struct`,它的行為很像一個數組,但具有值語義,通過讓struct在私有字段中保存一個數組,並且每次嘗試編寫數組都會創建一個包含數據的新數組從舊的數組中,修改新數組,並將修改后的數組存儲到該字段。 請注意,即使數組本身是一個可變類型,每個存儲在字段中的數組實例都是有效的不可變的,因為任何可能會使其變異的代碼都無法訪問它。

請注意,場景#1在泛型類型中非常常見; 例如,有一個字典的“值”是可變對象的身份是很常見的; 枚舉該字典將返回KeyValuePair的實例,其Value字段包含該可變類型。

場景#2不太常見。 沒有辦法告訴編譯器除了屬性設置器之外的結構方法將修改結構,因此在只讀上下文中應禁止它們的使用; 一個可以有一個行為類似於List<T> ,但是具有值語義,並且包含一個Add方法,但是嘗試在只讀結構實例上調用Add會產生偽代碼而不是編譯器錯誤。 此外,這種結構上的變異方法和屬性設定器通常表現得相當差。 當這些結構作為一個不可變的包裝器存在於其他可變類中時,它們可能是有用的; 如果這樣的結構永遠不會被裝箱,那么性能往往比一個類好。 如果只裝箱一次(例如通過鑄造到接口類型),性能通常可以與一個類別相比。 如果重復加框,性能可能比一類差。

這可能不是推薦的做法:請參閱http://msdn.microsoft.com/en-us/library/ms229017(VS.85).aspx

引用類型在堆上分配,內存管理由垃圾收集器處理。

值類型在堆棧或內聯中分配,並在超出范圍時釋放。

通常,值類型分配和釋放更便宜。 但是,如果它們用於需要大量裝箱和拆箱的場景,則與參考類型相比,它們的性能很差。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM