2013-02-01 27 views
0

我有一個有6個屬性的類,基本上有3對屬性,每對包含一件事的數據。所有這些屬性都是公開的,但設置它們是受保護的。它在下面的代碼所示:如何爲C#中的類中的結構提供不同的保護級別?

public class MyClass 
{ 
    public Data1Type Item1Data1 { get; protected set; } 
    public Data2Type Item1Data2 { get; protected set; } 
    public Data1Type Item2Data1 { get; protected set; } 
    public Data2Type Item2Data2 { get; protected set; } 
    public Data1Type Item3Data1 { get; protected set; } 
    public Data2Type Item3Data2 { get; protected set; } 
} 

由於每對屬性的作爲一個項目是基本上處理,我決定做一個結構,其看起來像這樣:

struct Item 
{ 
    Data1Type Data1; 
    Data2Type Data2; 
} 

所以我取代各對一個Item結構的屬性。

我現在面臨的問題是,我無法找到一種方法來獲得與之前相同的保護等級,具有3對屬性。我希望MyClass之外的所有內容都能夠獲得Item結構中的屬性,但只有MyClass和從中派生的類才能夠更改Item結構中的屬性。

我該怎麼做這樣的事情?它甚至有可能嗎?

+3

可變結構是邪惡的。 – Servy

回答

3

你可以讓你的結構只讀來保持對這些值的控制。這是在.NET中的部分使用的模式:

struct MyStruct 
{ 
    public readonly int Field1; 
    public readonly int Field2; 

    public MyStruct(int i, int j) 
    { 
     Field1 = i; 
     Field2 = j; 
    } 
} 

然後你就可以創建你的財產,你之前的方式一樣,知道內部結構的值將保持不變,除非你通過屬性setter。

+2

既然你公開地公開他們,'Field1'和'Field2'應該是屬性,而不是直接字段。 – Servy

+0

@Servit在結構中它不會有太大的區別,它使代碼冗長。你如何建議我們宣佈房產?有隻讀支持字段和只是一個getter?私人二傳手?如果這是一個類,我會同意 –

+3

'公衆詮釋Field2 {得到;私人設置;}'這是總共16個額外的字符,其中大部分將由Intellisense添加。對於許多微妙的好處來說,這是一項微不足道的額外工作。如果你需要全部寫出來,我可以看到它沒有工作的努力,但一旦自動實施的屬性被添加,沒有任何理由讓公有領域只是因爲它「更容易」。 – Servy

2

只需創建您的結構類型與受保護的setter的屬性:

public class MyClass 
{ 
    public Item Item1 { get; protected set; } 
    public Item Item2 { get; protected set; } 
    public Item Item3 { get; protected set; } 
} 

結構是值類型,所以客戶端無法從MyClass的項目Data1Data2屬性更改(客戶端都會有項目的複印件)。而對於受保護的setter,只有MyClass及其繼承者可以爲item設置新的值。如果您想要爲某件商品更新商品的數據,請使用class而不是struct

0

你或許應該閱讀更多關於struct - 它的意思是不變,這意味着,你不應該能夠改變Item的性能,無論是從MyClass或其他地方。

如果你看看Stan Petrovs answer,你可以看到應該如何構造結構。

MyClass那麼應該是這樣:

protected void SetItem1Data1(DataType1 newValue) 
{ 
    this.Item1 = new Item(newValue, this.Item1.Data2); 
} 
+0

結構類型可變的事實並非偶然,他們不是「意思」是不可改變的。 .net後面的一些人似乎認爲結構是輕量級的,並認爲任何偏離階級行爲的「缺陷」,但其他人清楚地意識到,分段可變的價值類型在他們自己的權利中是獨特有用的,因爲*他們的行爲不像班級類型。實際上,這兩個小組在一些使用情況方面都是正確的:嘗試像輕量級類對象一樣行爲的結構應該像不可變輕量級類對象那樣工作,但是... – supercat

+0

...還有其他一些用法,有一個結構,它的行爲就像一堆用膠帶粘在一起的變量。如果後一種風格的結構不是從「對象」下降的,但是如果每個這樣的類型「T」都可以有一個默認的(和可重寫的)隱式轉換和從「T [1]'或從'Object'派生的類似東西。這幾乎是現在的工作方式,只不過類型系統認爲盒裝和未裝盒的項目是相同的類型。 – supercat

0

只有兩種方式,其中一個結構類似:

someThing.someMember.nestedMember = someValue; 

可以是合法的:要麼someMember參考返回一個類實例,在這種情況下,someThing的介入將在返回參考文獻時立即停止,否則someThing.someMember必須是類別someThing的字段。它曾經是在C#中的法律即使someMember返回一個結構,以允許該someMember可能這樣做的可能性:

public class Thing { ... 
    private nestedType member_nestedMember; 
    public struct MemberProxy { 
     Thing _owner; 
     internal MemberProxy(Thing owner) {_owner = owner;} 
     nestedType nestedMember { 
      get {return _owner.member_nestedMember;} 
      set {_owner.member_nestedMember = value; } 
     } 
    } 
    public MemberProxy someMember {get {return new MemberProxy(this);} } 
} 

在這種情況下,MemberProxy實際上並不持有該數據nestedMember,而是持有對其所包含的實際位置的引用。因此,即使MemberProxy的實例不可寫,嘗試設置其nestedMember屬性也會起作用。不幸的是,即使有一些情況下,在只讀結構值上調用屬性設置器會有所幫助(ArraySegment會提供另一個這樣的示例),但還沒有定義屬性會告訴編譯器何時應該或不應該被允許。回到目前的情況,我會建議如果您的類型或派生類型可能希望在不改變兩個項目的情況下更改其中一個項目的任何實質性可能性,那麼您最好的選擇可能是聲明一個開放域結構的複合項目類型,並在該類別中包含protected該類型的字段以及返回它們的公共屬性。這樣做可以讓你的派生類的說:

item1.Data1 = whatever; 

,而外部的代碼必須使用Item1財產,即使Data1Item類型的暴露可寫的領域,試圖說:

item1.Data1 = whatever; 

不會編譯[請注意,如果Data1是一個讀/寫屬性,即使它可能會有用的理論,即使較老的編譯器也會接受這樣的語句,但在Data1是字段時會正確拒絕它]。如果你決定不公開公共可變的結構,你總是可以這樣做:

public struct Item 
{ 
    privateItem Value; 
    public Type1 Data1 {get {return Value.Data1; }} 
    public Type1 Data2 {get {return Value.Data2; }} 
    Item(privateItem src) 
    { 
    Value = src; 
    } 
} 

我個人實在看不出任何價值將包裹了一層額外的,但它可能幫助安撫「公衆可變結構是邪惡的」人羣。

相關問題