对于新闻编辑室系统,我有一个包含单个新闻故事的课程。在这个类中是一个私有变量,它包含一个通用的图像类列表。作为单个故事的想法可以包含多个图像。
问题是我应该将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 )
}
我的蜘蛛意识告诉我要做的更晚,因为它更抽象的东西。但另一方面,它创造了更多的代码。
答案 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)
大多数时候你只想循环遍历集合,所以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
}
}