2009-06-02 65 views
33

我發誓我已經看到了一個這樣的例子,但一直在谷歌搜索了一下,找不到它。C#以get only形式返回一個變量;組;

我有一個類有一個對象的引用,需要有一個GET;方法。我的問題是我不希望任何人能夠擺弄它,也就是說我希望他們能夠獲得它的只讀版本(注意我需要能夠從我的課堂中改變它)。

感謝

+1

我很驚訝有多少人誤解了這個問題。 Jon Skeet和Anton Gogolev說得對。 – 2009-06-02 13:41:13

+1

我沒有想到我誤會了 - 但仍然投票 - 哦, – ChrisF 2009-06-02 13:46:39

+0

這是一個詭計的問題:) – 2009-06-02 13:47:36

回答

51

沒有,有沒有這樣做的方式。例如,如果您返回List<string>(並且它不是不可變的),則呼叫者能夠添加條目。

正常的方法是返回一個不可變的包裝, ReadOnlyCollection<T>

對於其他可變類型,您可能需要在返回值之前克隆該值。

請注意,只是返回一個不可變的接口視圖(例如返回IEnumerable<T>而不是List<T>)不會阻止調用方迴歸到可變類型並進行變異。

編輯:注意從別的,除了,這種擔心是爲什麼不變類型更容易地推理代碼:)

6

返回精簡接口的引用:

interface IFoo 
    string Bar { get; } 

class ClassWithGet 
    public IFoo GetFoo(...); 
+1

理想情況下,包括IFoo的「私人」或「內部」實現,以便它不能被退回;) – jerryjvl 2009-06-02 13:36:47

3

這是不可能的原因之一。獲取並設置引用類型的訪問器獲取並設置對該對象的引用。您可以通過使用私有(或內部)setter來阻止對引用的更改,但如果對象本身被getter公開,則無法防止對該對象進行更改。

3

如果對象不是太複雜/廣泛,那麼在它周圍寫一個包裝。

例如:

class A { 
    public string strField = 'string'; 
    public int intField = 10; 
} 

class AWrapper { 
    private A _aObj; 

    public AWrapper(A aobj) { 
     _aObj = A; 
    } 

    public string strField { 
     get { 
      return _aObj.strField; 
     } 
    } 

    public int intField { 
     get { 
      return _aObj.intField; 
     } 
    } 
} 

所以,現在你要做的就是給你的客戶端代碼AWrapper類的一個實例,以便他們可以只使用你讓他們看到。

這可能會變得有點複雜,如果你的基類沒有設置好,可能無法很好地擴展,但對於最簡單的情況,它可能只是伎倆。我想這就是所謂的正面圖案(但不可以引用我這句話=))

0

我ReadOnlyCollection

同意見我簡單的代碼:

private List<Device> _devices; 
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices 
{ 
get 
{ 
return (_devices.AsReadOnly()); 
} 

}

ReadOnlyCollection dosen't有添加方法,所以用戶不能添加屬性,但它不保證,如果用戶可以通過調用他們的方法修改對象....

1

你的問題讀起來就像你正在尋找:

public PropertyName { get; private set; } 

不過,鑑於到目前爲止的答案,我不知道我在正確解釋你的問題。此外,我是誰來質疑Jon Skeet? :)

0

我以某種方式面對這個問題。 我有一個CategoryViewModel類,它有一個我想私人只讀屬性類別:

public CategoryViewModel 
{ 
    private Category { get; } 

} 

事實上,我希望它導出爲只讀到其他類。但是我不能做這樣的事情。 在我的情況下(也許它會幫助其他人),我想將它添加到存儲庫。我發現的唯一方法是有一個與存儲庫作爲參數1的功能和動作作爲參數2:

public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action) 
{ 
    action(repo, Category); 
} 

這樣,從其他地方,我可以做這樣的事情:

categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c)); 

這可以幫助其他人僅在某些情況下公開屬性並可以管理它們。