簡體   English   中英

為屬性分配集合引用時的最佳實踐

[英]Best practice when assigning a collection reference to a property

我非常注重C ++思維,需要一些特定C#問題的指導。 我們假設我們有以下類:

public class Foo
{
    private IList<Bar> _bars = new List<Bar>(); // Note IList<> vs List<>.

    public IList<Bar> Bars
    {
        get { return _bars; }
        set
        {
            ...
        }
    }
}

現在,在地方的... ,我傾向於清算_barsAddRange項目從set參數value ,而不是只分配value_bars 我看到它,方式是,我想保持引用同一個項目 ,該value項的引用,而不是實際IList<Bar>value引用。

那個錯誤的想法在我身邊嗎? 你覺得怎么樣?

編輯:經過一些評論后,我意識到我必須補充一點,我希望能夠在Foo ctor中使用現有的Bars集合並從該集合中初始化_bars。 所以,到目前為止,通過該修訂和評論,這感覺更好:

public class Foo
{
    private readonly List<Bar> _bars = new List<Bar>();

    public Foo(IEnumerable<Bar> bars)
    {
        _bars.AddRange(bars);
    }

    public IList<Bar> Bars
    {
        get { return _bars; }
    }
}

好點嗎?

如果我們討論的是業務(域)對象,我會公開IEnumerable<T>以及適合該集合的任何方法,通常是Add,Remove和Clear。 我幾乎從不公開一個集合的setter。

是否有必要能夠使您的Foo實例的Bars屬性引用另一個List?

如果沒有,那么我寧願沒有酒吧的屬性設置器。

如果有必要將Bars屬性設置為另一個List實例,那么我想我發現你的setter修改列表會很奇怪。 我的意思是:當我為該屬性分配另一個Bars列表時,我會假設我的Foo實例然后包含我已分配給該屬性的列表中可用的Bars。 不多也不少。 我發現突然收集包含更多(或更少)條形圖,我會覺得很奇怪......

根據您提問的推斷要求:

public class Foo
{
    private readonly IList<Bar> _bars = new List<Bar>();

    public IList<Bar> Bars
    {
        get { return _bars; }
    }
}

當然,不需要為Bars屬性公開setter。 在內部,您持有對集合的引用,Kent建議可以將其標記為Readonly。 通過getter,調用者可以使用可用的方法(Add,Remove,Clear,AddRange等)對集合執行他們想要的操作,但至關重要的是,他們永遠不能更改您對集合對象持有的內部引用。

然后,您可以控制允許的方法。 正如Jamie所建議的那樣,擁有屬性返回類型IEnumerable會導致Bars屬性暴露一個只讀集合。 公開IList意味着可以修改集合的內容。 酒店的安裝人員可以將其打開,讓呼叫者做他們想做的事情,而且你不再受控制。

編輯

按照上面的問題編輯。 這實際上取決於Foo對象的使用方式。

因為您主要關注的是從現有的Bar對象列表中初始化Foo ...

IList<Bar> bars = ...some list of Bars previously constructed...

您最新的Foo代碼示例強制調用者通過構造函數初始化,但也允許他們通過屬性更改集合

Foo foo = new Foo(bars);
...
foo.Bars.Clear();
foo.Bars.AddRange(bars);

當允許通過構造函數初始化對象時,您需要問自己為什么要這樣做。 是嗎...

  1. 為了來電者的方便? 允許調用代碼提供可以隨后通過屬性更改的值。
  2. 因為你想限制對象的使用方式? 強制值(或某些值組合)在對象構造上設置,並在對象的整個生命周期內保持固定。

您需要問自己 - 您是否希望調用者能夠在構建Foo對象后更改Bars集合的內容?

如果否 - 使Bars屬性公開只讀集合。
如果是 - 將默認構造函數添加到Foo對象,以便調用者不必提供列表來初始化它。 但如果他們通過重載構造函數選擇,他們可以選擇這樣做。

我對這些屬性的setter很好,但我通常不允許空值,因為null很少有空的列表具有不同的業務含義。

set { _bars = value ?? new List<Bar>();}

我認為從getter返回_bars引用有點狡猾。 你真的希望班級的客戶能夠修改列表的內容嗎?

所以我會做以下事情:在構造/設置上復制並返回getter的只讀視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM