2009-11-04 25 views
1

對於新聞室系統,我有一個包含單個新聞故事的類。這個類內部是一個私有變量,它擁有一個通用的圖像類列表。作爲單一故事的想法可以包含多個圖像。班級設計:直接或通過方法訪問列表<T>?

的問題是我應該做的List變量公衆,通過解決清單,以便我可以添加/刪除圖像直接

public class News 
{ 
    private _images List<Images>(); 

    public Images 
    { 
     get { return _images; } 
     set { _images = value } 
    } 
} 

我應該做的清單私有變量,然後創建方法來操縱它:

public class News 
{ 
    private _images List<Images>(); 

    public void AddImage(Image image) 
    public Image GetImage(int imageId) 
    public int GetImageCount() 
    public void DeleteImage(int imageId) 
} 

我的蜘蛛感覺告訴我做更晚,因爲它更抽象的東西。但另一方面,它創建更多的代碼。

回答

7

我會將列表的只讀視圖分解爲IList或IEnumerable以及用於添加和刪除元素的方法。像這樣:

public class News 
{ 
    private _images List<Images>(); 

    public IList<Image> Images 
    { 
     get {return _images.AsReadOnly(); } 
    } 

    public void AddImage(Image image) 
    { 
     _images.Add(image); 
     // Do other stuff... 
    } 

    public void DeleteImage(Image image) 
    { 
     _images.Remove(image); 
     // Do other stuff... 
    } 
} 
+0

我猜Images圖像屬性缺少'get {'部分? – 2009-11-04 12:25:03

+0

它確實;-)我修好了。 – 2009-11-04 12:32:03

+0

+1 .AsReadOnly()引起我的注意。 – Gregory 2009-11-04 12:48:33

8

通過公開List,您可以看到一個實現細節。它會使短期內更容易,但如果您決定例如在短時間內將會很難。將列表更改爲其他容器(也許您需要查找字典或其他內容)。

我會封裝它,因爲它會使類型在未來更容易維護和增強。

1

這取決於您是否需要/(需要)來控制添加/獲取和刪除圖像或更改容器的可能性。

3

如果暴露列表作爲一個屬性,然後纔有可能做到從類的外部以下內容:

News.Images = new List<Images>(); 

這是你想要的嗎? (你不應該,因爲它打破了封裝原則而各種)

如果沒有,那麼使用的ICollection <牛逼>接口:

class News 
{ 
    public ICollection<Image> Images 
    { 
     get; 
     private set; 
    } 
} 

class News 
{ 
    private List<Image> images = new List<Image>(); 
    public ICollection<Image> Images 
    { 
     get 
     { 
      // You can return an ICollection interface directly from a List 
      return images; 
     } 
    } 
} 

ICollection的<牛逼>有方法如添加,刪除,清除,計數。

如果你想有一個只讀容器返回ReadOnlyCollection

class News 
{ 
    private List<Image> images = new List<Image>(); 
    public ReadOnlyCollection<Image> Images 
    { 
     get 
     { 
      // This wraps the list in a ReadOnlyCollection object so it doesn't actually copy the contents of the list just a reference to it 
      return images.AsReadOnly(); 
     } 
    } 
} 
0

公開一個只讀實現列表和揭露操縱列表的方法。我會做這樣的:

public class News 
{ 
    private IList<Image> _images; 

    public void News() 
    { 
     _images = new List<Image>(); 
    } 

    public void AddImage(Image image) { ... } 
    public void RemoveImage(Image image) { ... } 

    public IEnumberable<Image> Images 
    { 
     get { return _images; } 
    } 
} 

注意,圖像屬性可強制轉換爲列表,但如果需要的話,你可以在ReadyOnlyCollection包裝返回。 Count()和ElementAt()擴展方法取代您的GetImageCount和GetImage方法。

0

對於訪問元素,可以考慮使用ReadOnlyCollection或IEnumerable類型。但是爲了保證封裝的安全,你應該使用insert/remove方法,這樣你就不需要這個屬性了。

編輯:打字這個答案時有人打我給它;)

0

我認爲這是一個設計考慮,只有你才能決定。您的第二種方法是隱藏實施細節,您使用List來存儲圖像。另一方面,第一種解決方案爲您提供了一個優勢。您可以使用所有的List方法,包括那些始終有用的擴展。使用第二種解決方案,您也可以實施ToList()方法,該方法將返回一個新構建的List。對List的更改不會影響您的class的內部結構。不利的一面是,如果內部Image List太大,可能會影響性能,因爲它總是會在ToList()上生成新的List,但我不希望此方法被多次調用。

另一種解決方案是公開ReadOnlyCollection

0

如果直接暴露在列表中,您將不得不依靠它的力學所有圖片相關的操作(添加,刪除,計數,...)

我還是會暴露圖片的集合(ReadOnlyCollection通常很好),以使開發人員和消費者對列表的訪問操作更容易,但是所有創建/更新/刪除邏輯都應該包裝在您的類中。

1

Davy Brion在上週做了一個帖子。他傾向於暴露一個IEnumerable屬性並提供一個添加操作的remove方法。

大多數情況下你只想循環訪問集合,所以IEnumerable <>就可以實現。此外,當切換到另一個ORM時,您可以根據需要切換實際的實現(List,Set,...),這可能證明非常有價值。

http://davybrion.com/blog/2009/10/stop-exposing-collections-already/

+0

通過公開ICollection,您可以更改底層實現 - 唯一不使用ICollection的參數是如果您需要在集合內容更改時收到通知。 – 2009-11-04 12:53:51

+0

ICollection確實是一個有效的選擇,這一切都取決於您想要對「集合」執行什麼操作。如果你只是想循環它:IEnumerable,如果你想知道在某個點的大小:ICollection。這是一個關於這個級別的品味問題,只要你不使用IList就沒關係。 – 2009-11-04 13:10:27

+0

同意 - 這是知道每種方法的優點和缺點的情況。我似乎記得在某個地方使用Linq .Count只會返回列表的.Count而不是循環遍歷所有項目。 – 2009-11-04 13:37:44

0

我只是想揭露列表作爲一個IList:

public class News 
{ 
    private List<Image> _images; 

    public IList<Image> Images 
    { 
     get { return _images; } 
     set { _images = value; } 
    } 
} 

如果你以後想改變實現,你可以做到這一點沒有毀約:

public class News 
{ 
    public News(SomeCollection<Image> images) 
    { 
     _images = images; 
     Images = new ListView(this); 
    } 

    private SomeCollection<Image> _images; 

    public IList<Image> Images { get; private set; } 

    private class News.ListView : IList<Image> 
    { 
     public ListView(News news) 
     { 
      _news = news; 
     } 

     private News _news; 

     // Implement the methods to manipulate _news._images 
    } 
}