2013-02-19 81 views
1

好吧,這是比實際需求更好奇。有沒有一種方法可以防止結構被檢測或我可以有一個類將被複制?

比方說,我有這個類:

public sealed class Entity 
{ 
    int value; 

    Entity() 
    { 

    } 

    public static implicit operator Entity(int x) 
    { 
     return new Entity { value = x }; 
    } 
} 

我不希望這個類給類以外的實例化,這工作做。但是這裏的Entity將被引用,而不是像值類型那樣被複制。這個類很小,我希望它表現得像值類型。另外,如果我比較Entity的兩個實例,如e1 == e2它會給參考相等(好吧,我可以重載==但這是更多的工作)。所以,我想使它成爲一個結構:

public struct Entity 
{ 
    int value; 

    public static implicit operator Entity(int x) 
    { 
     return new Entity { value = x }; 
    } 
} 

但現在有人可以很容易做到new Entity()

我的問題是沒有一種方法可以有一個類型(結構/類),該

1)將被複制的每個的值被訪問時,使

Entity e1 = 1; 
Entity e2 = e1; 
ReferenceEquals(e1, e2); // prints false, just like any value type 

2)具有值語義平等比較時

Entity e1 = 1; 
Entity e2 = 1; 
e1.Equals(e2); // prints true 

// this is easy though by overriding default equality. 

3)沒有被實例化的類型的範圍之外:

Entity e = new Entity(); // should not compile 

基本上接近枚舉的行爲。我當然可以沒有它,只是學習。

+0

你的意思是短重寫「等於」方法或類上的「==」操作符來執行,只要你想的比較? – 2013-02-19 15:02:32

+0

@DavidW是的,這是可能的。但它仍然不會給類的價值類型語義,或換句話說我的要求1. – nawfal 2013-02-19 15:09:37

回答

2

它不可能在C#中重新定義或嘗試隱藏結構的默認構造函數,因爲C#編譯器會基於假設無參數構造函數不做任何事情來常規地編譯代碼。見Why can't I define a default constructor for a struct in .NET?

你的選擇是要麼

  • 使用類
  • 確保您的結構中的默認值有一定的意義(例如,在你的情況整型將被初始化爲0) - 這是枚舉做(回想起枚舉初始化爲0)。

我的建議是使用一個類,直到您確定存在性能問題。

-1

使所有構造函數(除了靜態構造函數)privateEntityprotected也可以工作,但由於其sealed,這並沒有多大意義。

+0

你似乎沒有得到我的問題。將構造函數設爲私有使其不可實例化,但它是否符合我的要求1?沒有.. – nawfal 2013-02-19 15:07:15

+0

你爲什麼不重寫'Equals'? – 2013-02-19 15:11:46

+0

是的,這是可能的,但仍然是一個引用類型,而不是值類型,否則將被複制。我將編輯我的問題。 – nawfal 2013-02-19 15:12:50

1

一種類型沒有發言可以發生該類型的存儲位置。任何類型的存儲位置都可以存在,或者其內容被相同類型的其他位置的內容覆蓋,而類型本身沒有任何發言權。引用類型的存儲位置包含類引用;當它出現時,它將是一個空引用。引用類型的存儲位置只能存儲空引用以外的任何東西的唯一方法是,如果創建了該類型的實例,並且 - 涉及完全信任代碼和反射的某些情況外 - 引用類型將完全控制可能發生的情況。

相比之下,值類型的存儲位置是該類型的一個實例。因此,結構無法控制如何成立。什麼樣的結構可以控制 - 在一定程度上 - 它的領域可以包含哪些價值。在有限的信任方案中,如果結構的代碼將該值寫入結構的某個實例,則私有結構字段只能假定非默認值(如果該值被寫入結構的任何實例,即使受限信任代碼與訪問該實例可能能夠使用多線程重疊的讀取和寫入產生結構與組合,該結構本身絕不會自己創建的字段值)。

我建議創建一個類類型的單個私有字段一個struct。您無法阻止代碼創建default(Entity),但這並不意味着您必須允許代碼對其中的任何內容執行任何操作。它Equals方法應在與其他任何東西相比,工作不夠好比較的另一個默認實例時返回truefalse,並GetHashCode應該爲所有默認實例返回相同的值,但任何其他的方法可以拋出一個異常。

+0

如果我擁有班級類型的私人支持字段,它會給我帶來什麼好處?一個結構仍然是可實例化的。我會悲傷地用我最初的方法(賈斯汀的回答)。 – nawfal 2013-02-20 06:52:52

+0

@nawfal:在一個結構結束語一個類可以讓你暴露從什麼類本身會暴露不同的方法,並且還允許您控制默認情況下的行爲。任何人都可以創建任何類型的變量 - 類或結構 - 並調用傳遞該變量的方法。在類類型的情況下,默認值變量會比較等於'null',並試圖調用任何方法將拋出'NullReferenceException'。通過一個結構,你可以決定哪些效果方法應該對默認實例有效。 – supercat 2013-02-20 16:17:12

相關問題