2009-01-14 51 views
3

我有一個類,定義了一個只讀屬性,有效地暴露了私人領域,像這樣:限制訪問方法調用只讀屬性

public class Container 
{ 
    private List<int> _myList; 

    public List<int> MyList 
    { 
     get { return _myList;} 
    } 

    public Container() : base() 
    { 
     _myList = new List<int>(); 
    } 

    // some method that need to access _myList 
    public SomeMethod(int x) 
    { 
     _myList.Add(x); 
    } 
} 

現在這是不可能的,爲消費者管理我的財產直接,所以代碼像aContainer.MyList =新列表();生成編譯時錯誤。 然而,消費者是絕對自由調用各種對他得到的參考方法,所以這是完全合法的代碼

Container c = new Container(); 
Console.WriteLine(c.MyList.Count); 
c.MyList.Add(4); 
Console.WriteLine(c.MyList.Count); 

哪種擊敗了整個只讀概念。

有沒有什麼理智的解決方法可以讓我擁有一個真正的只讀引用propery?

P.S.我不能只是返回一份清單的副本,因爲那時用戶會認爲他做了所有必要的更改,但是可惜...他們將會消失。

+0

忘記在代碼中寫入_myList是隻讀的。 ;) – Spoike 2009-01-14 14:34:08

+0

該字段本身不是隻讀的,它是從其他類方法訪問的,只有屬性是隻讀的。 但是,即使聲明該字段只讀也沒有幫助:( – SWeko 2009-01-14 14:38:49

回答

2

參考是"readonly",實際的對象。即您不能用另一個對象替換引用。所以如果你有一個類打破它這樣的:

public class Container 
{ 
    private readonly List<int> _myList; 

    public List<int> MyList 
    { 
     get { return _myList;} 
    } 

    public Container() : base() 
    { 
     _myList = new List<int>(); 
    } 

    public void BreakReadOnly() 
    { 
     _myList = new List<int>(); 
    } 
} 

...那麼它甚至不會編譯。這是因爲readonly字段不能與其他任何對象重新分配。在這種情況下,BreakReadOnly將嘗試分配一個新的列表。

如果你真的想它的只讀集合,那麼你可以做這樣的:

public ReadOnlyCollection<int> MyList 
    { 
     get { return _myList.AsReadOnly(); } 
    } 

希望這有助於。

更新:刪除使用IEnumerable。

1

看看靜態Array.AsReadOnly()方法,您可以使用它來返回一個數組的封裝器,以防止它被修改。

5

不要直接引用您的列表。取而代之的是返回一個ReadOnlyCollection,或者如果列表返回類型設置爲石頭,則返回列表的副本。他們可以做任何他們想要的副本,而不會影響原文。

0

你想_myList,這是一個引用類型是隻讀的。嗯,它是隻讀的,沒有隻讀概念的失敗。

CLR以引用類型的readonly屬性的方式實現引用(指向對象的指針,如果需要的話)是隻讀的,而引用指向的對象可以修改。

要解決此問題,您需要自己只讀對象的成員字段,因爲您無法通過將只讀標誌附加到對象的引用來使整個對象只讀。

你可以實現你的不可變泛型集合類,它的行爲方式與列表<>對象相同,但只有成員。

2

你可以返回一個readonly Collection這樣的:

public ReadOnlyCollection<int> MyList 
    { 
     get { return _myList.AsReadOnly(); } 
    } 

或返回一個新的列表中,使主叫方可以更改列表不改變原來的列表中。

public List<int> MyList 
    { 
     get { return new List<int>(_myList)} 
    }