2013-11-26 67 views
4
class A 
{ 
    public int x { get; set; } 
    // other properties 
} 

class S 
{ 
    public A GetA(...); 
} 

我想作以下限制:
A可以在裏面S只能修改。當其他人通過GetA()得到A時,他只能得到A的屬性,而不能修改它們。C#類成員訪問問題

我決定做一個新的功能,在S返回另一個對象:

class B 
{ 
    A a; 
    public int x { get { return a.x; } } 
    // replicate other A's properties 
} 

有沒有更好的解決辦法?

回答

7

你可以做的A接口只具干將,並返回從GetA

public interface IA 
{ 
    int x { get; } 
} 

class A : IA 
{ 
    public int x { get; set; } // nothing stopping you having a setter on the class 
} 

class S 
{ 
    private A a = new A(); // you can call the setter internally on this instance 
    public IA GetA(){ return a; } // when someone gets this thy only get the getter 
} 

當然,還有什麼能阻止別人鑄造GetA的結果A,然後他們有二傳手 - 但是你真的沒有辦法做到這一點!

+1

+1我們認爲一樣:)。刪除我的答案.. –

+1

我認爲他的一個要求是* A只能在S *內修改。但是現在'A'可以在任何地方進行修改,只要有人設法得到它。這完全是爲了讓最終用戶很難,可能會嵌套'A'在這裏更好。 – nawfal

+0

感謝您的評論。實際上,我需要A在S所在的命名空間內進行修改,所以我決定使用私有A – Ivan

-1

另一種選擇是返回A的副本,而不是A本身。

class S 
{ 
    public A GetA() { return a.Clone(); } 
} 

您還可以使A結構,這會導致這自動發生。 這當然取決於多大或複雜A是。在大多數情況下,界面可能會更好,正如Jamiec的答案中所詳述的。

+1

Downvoters care to comment? – Rotem

+2

我沒有downvote,但我認爲你誤讀了這個問題:)你錯過的關鍵部分「當別人通過GetA()獲得A時,他只能得到A的屬性,而不能修改它們」 - 克隆A不滿足這個要求 – Jamiec

+0

@Jamiec它的確如此,就是說他在A上修改的任何屬性都不會傳播到'S'中找到的'A',這是OP要執行的。如果'A'是一個只包含兩個'int'的類(想''Point''),我寧願克隆它並返回它,而不是返回一個接口。 – Rotem

1

也許嵌套類也可以滿足您的需求?

public class S 
{ 
    private A ClassA { get; set; } 

    public S() 
    { 
     ClassA = new A(); 
    } 

    private class A 
    { 
     public int TestProperty { get; set; } 
    } 

    public int GetClassATestProperty 
    { 
     get 
     { 
      return this.ClassA.TestProperty; 
     } 
    } 
} 
0

您可以更改A的實現,以便引入只讀模式。創建實例後,可以根據需要設置屬性。一旦有人獲得實例,您可以啓用只讀模式。在只讀模式下,制定者應該拋出異常,例如, InvalidOperationException異常。爲了避免大量的if (IsReadOnly) ...;語句,您可以使用策略模式來更改實例的行爲。
根據您的需要,還可以在調用者請求對象後激活ReadOnly模式來創建副本。這將允許在第一次請求實例之後進行更改。
這對接口的一個優點是調用者不能使用強制轉換來訪問setter。雖然你不必實現一個接口,但只讀模式的實現應該是值得的。這取決於你對風險和損害的分析。

1

你是類似於C++中的friend關鍵字。 And there is no equivalent in C# sadly.。我看到一些可能性。

  1. S一種A?在這種情況下,繼承可以幫助您,因爲您可以通過protected修飾符進行限制。

    class A 
    { 
        public int x { get; protected set; } 
    } 
    
    class S : A 
    { 
        public A GetA() { return this; } //or something like that. 
    } 
    
  2. 是否A事情只有S?在這種情況下,您可以使A成爲S的私有內部類,如Cloud9999Strife所示。

  3. 也許最好將離開A作爲一個抽象類或接口,爲市民和有嵌套在S它的具體實現 - 兩個Jamiec的組合和Cloud9999Strife的答案。

    public abstract class A // or interface 
    { 
        public abstract int x { get; } 
    } 
    
    class S 
    { 
        public A GetA() { return AImplInstead(); } 
    
        class AImpl : A 
        { 
         // nothing stopping you having a setter on the class 
         public override int x { get; set; } 
        } 
    } 
    

在本質上,如果A可以由一個通用類進行修改,那麼它可以是無處不在的,除非有AS之間的關係。這就是C#的設計。現在我們所能做的就是讓最終用戶難以做到(即修改A)。暴露界面是其中的一部分。嵌套使其更深層次。請注意,還有反射會破壞所有封裝。