类设计:直接或通过方法访问List <t>?</t>

时间:2009-11-04 12:05:23

标签: c# .net class oop

对于新闻编辑室系统,我有一个包含单个新闻故事的课程。在这个类中是一个私有变量,它包含一个通用的图像类列表。作为单个故事的想法可以包含多个图像。

问题是我应该将List变量设为公共,以便我可以通过直接寻址List来添加/删除图像

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

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

我应该将List变量设为私有,然后创建操作它的方法:

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 )
}

我的蜘蛛意识告诉我要做的更晚,因为它更抽象的东西。但另一方面,它创造了更多的代码。

10 个答案:

答案 0 :(得分:8)

通过公开List,您可以公开实现细节。这会让你在短期内变得更容易,但是如果你决定例如,你将很难过。将列表更改为其他容器(可能需要使用Dictionary进行查找或其他内容)。

我会封装它,因为它将使该类型在将来更容易维护和增强。

答案 1 :(得分: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...
    }
}

答案 2 :(得分:3)

如果您将列表公开为属性,则可以从类外部执行以下操作:

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

这就是你想要的吗? (你不应该因为它打破了各种封装原则)

如果不是,则使用ICollection&lt; T&gt;接口:

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&LT; T&GT;有添加,删除,清除,计数等方法。

如果您希望只读容器返回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();
        }
    }
 }

答案 3 :(得分:1)

这取决于您是否需要/(需要)控制添加/获取和删除图像或更改容器的可能性。

答案 4 :(得分:1)

Davy Brion上周在这个帖子上发了帖子。他赞成暴露IEnumerable&lt;&gt;财产和提供添加&amp;删除操作方法。

大多数时候你只想循环遍历集合,所以IEnumerable&lt;&gt;会做的。此外,您可以在需要时切换实际的实现(List,Set,...)而不会有任何麻烦,当切换到另一个ORM时,这可能非常有价值。

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

答案 5 :(得分: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; }
    }
}

请注意,Images属性可以强制转换为List,但如果需要,可以在ReadyOnlyCollection包装中返回它。 Count()和ElementAt()扩展方法替换了GetImageCount和GetImage方法。

答案 6 :(得分:0)

要访问元素,可以考虑使用ReadOnlyCollection或IEnumerable类型。但是,为了确保封装,您应该使用insert / remove方法,这样就不再需要属性集了。

编辑:有人在输入这个答案时打败了我;)

答案 7 :(得分:0)

我认为这是一个只有你自己才能决定的设计考虑因素。您的第二种方法是隐藏您使用List来存储图像的实现细节。另一方面,第一个解决方案为您提供了一个优势。您可以使用所有List方法,包括始终有用的扩展名。使用第二个解决方案,您还可以实现一个ToList()方法,该方法将返回一个新构造的List。对此List的更改不会影响class的内部结构。如果内部图像List太大,则可能会影响性能,因为它总是会在List上构建一个新的ToList(),但我不希望这种方法是多次打电话。

另一种解决方案是公开ReadOnlyCollection

答案 8 :(得分:0)

如果您直接公开List,则必须依赖它的所有与Image相关的动作(Add,Delete,Count,...)

我仍然会公开一组Images(ReadOnlyCollection通常很好),以便开发人员和使用者更容易访问列表,但所有创建/更新/删除逻辑都应该包含在你的类中。 / p>

答案 9 :(得分: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
    }
}