我们正处于将代码从C ++转换为C#的项目的最开始。一位同事提出了一个包含List<T>
成员的列表类。他没有从List<T>
派生,因为他需要在允许项目添加到列表之前进行一些验证。
有一段时间,我认为从CollectionBase
派生自定义列表可能会有所帮助,但我认为CollectionBase
已经过时,因为我们有通用类。我在此处发现的一篇帖子说,具有类似问题的用户应该来自列表<T
&gt;并在派生类中执行验证,但它没有说明如何做到这一点。
例如,假设我想要一个只包含偶数整数的列表。在将其添加到列表之前,我将如何实现一个确保整数为止的检查?
答案 0 :(得分:9)
您必须实施IList<T>
。从List<T>
派生是不够的,因为诸如Add
之类的方法不可覆盖 - 你可以放弃继承并隐藏基类实现,但那是......脏。并且不安全。
所以只需实现IList<T>
并使用合成:
public class EvenIntsList : IList<int>
{
private readonly IList<int> _list;
public EvenIntsList()
{
_list = new List<int>();
}
public void Add(int item)
{
if(item % 2 == 0)
_list.Add(item);
else
throw new ArgumentException("This list only allows even integers.", "item");
}
}
您还必须为其他IList<T>
方法提供传递实现,例如:
public IEnumerable<int> GetEnumerable()
{
return _list.GetEnumerable();
}
答案 1 :(得分:4)
虽然我认为除了存储数据之外在集合中执行操作是一种糟糕的技术,但我会执行以下操作:
类似的东西:
public class ValidatedList<T> : IList<T>
{
private Func<T, bool> validator;
private List<T> list = new List<T>();
public ValidatedList()
{
}
public Func<T, bool> Validator
{
get { return validator; }
set { validator = value; }
}
public void Add(T item)
{
if (validator != null && validator(item))
{
list.Add(item);
}
}
//other IList<> methods go here
}
根据您想要列出的“激进”的方式,如果验证失败,您可以抛出异常,或者如果未设置验证器,则允许在列表中添加项目(我不添加项目)这个样本)。
修改强>
同样如dcastro所建议的那样,在属性中使用验证器会导致其他影响,例如更改验证器可能会使列表中已有的项无效。它可以通过构造函数添加,并且可以跳过属性。
答案 2 :(得分:0)
如何使用带有抽象验证方法的通用基类来实现您想要的任何自定义列表?
然后,您可以从内部列表中继承任何其他要公开的接口。 (如IList)
显然你需要再添加一些验证..
/// <summary>
/// Abstract Generic base class
/// </summary>
/// <typeparam name="T">Type</typeparam>
public abstract class CustomList<T>
{
private List<T> _list;
public CustomList()
{
_list = new List<T>();
}
public T this[int i]
{
get
{
return _list[i];
}
}
public void Add(T item)
{
if (this.ValidateItem(item))
_list.Add(item);
else
throw new ApplicationException("Your exception here");
}
/// <summary>
/// Validation method
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
protected abstract bool ValidateItem(T item);
}
/// <summary>
/// Int list type
/// </summary>
public class IntCustomList : CustomList<int>
{
protected override bool ValidateItem(int item)
{
return item % 2 == 0;
}
}
/// <summary>
/// Test class
/// </summary>
public class Test
{
public void Test()
{
IntCustomList list = new IntCustomList();
list.Add(1);
list.Add(2);
}
}