关于c:在类中有一个集合

Having a collection in class

本问题已经有最佳答案,请猛点这里访问。

当一个类必须具有某种对象的容器(集合)时,有几个选项,我想知道我更喜欢什么实现。

以下是我找到的选项:

1
2
3
4
5
6
7
8
9
10
11
12
public class AClass : IEnumerable<string>{
   private List<string> values = new List<string>()

   IEnumerator IEnumerable.GetEnumerator()
   {
      return GetEnumerator();
   }

   public IEnumerator<T> GetEnumerator(){
      return values.GetEnumerator();
   }
}

优点:aclass不依赖于集合的具体实现(在本例中是列表)。

缺点:aclass没有用于添加和删除元素的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class AClass : ICollection<string>{
   private List<string> values = new List<string>()

   IEnumerator IEnumerable.GetEnumerator()
   {
      return GetEnumerator();
   }

   public IEnumerator<T> GetEnumerator(){
      return values.GetEnumerator();
   }

   //other ICollectionMembers
}

优点:与IEnumerable plus相同,它具有添加和删除元素的接口

缺点:ICollection接口定义了其他很少使用的方法,仅仅为了接口而实现这些方法会很无聊。此外,IEnumerable LINQ扩展还负责其中的一些扩展。

1
2
3
public class AClass : List<string>{

}

优点:不需要实现任何方法。调用方可以调用列表实现的任何方法

缺点:aclass依赖于集合列表,如果更改了,则可能需要更改一些调用方代码。而且aclass不能继承任何其他类。

问题是:我应该选择哪一个来声明我的类包含一个同时支持添加和删除操作的集合?或其他建议…


我的建议只是在你的类中定义一个通用的列表,并编写额外的AddRemove方法,这样就可以实现IEnumerable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class MyClass : IEnumerable
{
    private List<string> myList;

    public MyClass()
    {
        myList = new List<string>();
    }

    public void Add(string item)
    {
        if (item != null) myList.Add(item);
    }

    public void Remove(string item)
    {
        if (myList.IndexOf(item) > 0) myList.Remove(item);
    }

    public IEnumerable<string> MyList { get { return myList; } }

    public IEnumerator GetEnumerator()
    {
        return myList.GetEnumerator();
    }
}

如果您不想实现自己的集合,这是最好的方法。您不需要实现到AddRemove方法的接口。我想这类附加方法适合您的需要。


好吧,这确实是一个基于意见的问题,它并不是专门用来做什么的。然而,正如您所列出的,所有实现都有不同的pro和con,实际上,您实现的是最适合应用程序使用的选项。

在我个人的观点中,我将使用选项1并添加与内部集合交互所需的方法。这是非常简单的实现和使用。

类似的东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class AClass : IEnumerable<string>
{
    public AClass()
    {
        this.values = new List<string>();
    }

    private readonly List<string> values;

    public void Add(string inputString)
    {
        this.values.Add(inputString);
    }

    public void Remove(string inputString)
    {
        this.values.Remove(inputString);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator()
    {
        return values.GetEnumerator();
    }
}

现在它有了简单的添加/删除功能。另外请注意,我使用了一个readonly列表,因为调用构造函数后,您的列表不需要休息。

根据注释更新。

是的,您确实已经从一个列表转换到了AClass其他类(无论如何您都必须转换)。我已经添加了一个额外的构造函数和一个隐式运算符来从构造函数中的列表或IEnumerable强制转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class AClass : IEnumerable<string>
{
    public static implicit operator AClass(List<string> collection)
    {
        return new AClass(collection);
    }

    public static implicit operator List<string>(AClass aClass)
    {
        return aClass.values;
    }

    public AClass()
    {
        this.values = new List<string>();
    }

    public AClass(IEnumerable<string> collection)
    {
        this.values = collection.ToList();
    }

    private readonly List<string> values;

    public void Add(string inputString)
    {
        this.values.Add(inputString);
    }

    public void Remove(string inputString)
    {
        this.values.Remove(inputString);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator()
    {
        return values.GetEnumerator();
    }
}

这可以作为以下方式使用:

1
2
3
4
5
6
List<string> listA = new List<string>();

AClass classA = new AClass(); //parameterless constructor
AClass classA1 = new AClass(listA); //simple constructor call with collection
AClass classA2 = (AClass)listA; //direct cast
List<string> listB = (List<string>)listA; //cast back to a list

只是个主意,还是个人意见。


我喜欢你解释你想法的方式。

您发现了3种完美的解决某些问题的方法。你的利弊让我觉得你理解得对。

没有解决所有问题的灵丹妙药。但是你最好有一个软件架构师工具箱,里面装满了设计模式和一些常识。

下次面对挑战时,请使用最好的工具!


这只是对塞尔曼建议的一小部分修改,因此他的回答符合我的期望:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class MyClass : IEnumerable<string>
{
   private List<string> myList;

   public MyClass()
   {
       myList = new List<string>();
   }

   public ICollection<string> MyList { get { return myList; } }

   IEnumerator IEnumerable.GetEnumerator()
   {
      return GetEnumerator();
   }

   public IEnumerator<T> GetEnumerator(){
      return myList.GetEnumerator();
   }
}