从静态List <myclass>中删除元素

时间:2017-05-02 11:51:23

标签: c# list static

方法List<T>.Remove(T)我遇到了一些问题。我有一个类(描述下来)用作列表的类型 我的班级是:

public class MyClass
{
   public string ID { get; set; }
   public myEnum CallType { get; set; }
   public object ObjToStore { get; set; }
}

我的List<T>实例化如下:

private static List<MyClass> ListOfStoreObjects = new List<MyClass>();

我的麻烦在于我将这些内容存储到这些列表中,我无法删除它们。我使用这些列表将临时数据存储在Web服务中(我想'走这条路',所以请不要告诉我其他解决方案,thx)当然,一旦使用这些数据我就设法删除他们来自这个“缓冲区”。那么,有一种方法可以从静态列表中删除一个元素吗?

修改

我使用的添加功能是:

public bool AddToQueue(string id, myEnum callType, object objToAdd)
{
   try
   {
      MyClass elementToAdd = new MyClass();
      elementToAdd.ID = id;
      elementToAdd.CallType = callType;
      elementToAdd.ObjToStore = objToAdd;
      ListOfStoreObjects.Add(elementToAdd);

      return true;
   }
   catch
   {
      return false;
   }
}

我用来检索我需要的对象然后从列表中删除它的函数:

 public object RetrieveObj(string id, myEnum callType)
 {
     object obj = null;

     foreach(var element in ListOfStoreObjects)
     {
         if( element.ID == id && element.CallType == callType)
         {
             obj = element.ObjToStore;
             break;
         }
     }

     MyClass itemToRemove = new MyClass();
     itemToRemove.ID = id;
     itemToRemove.CallType = callType;
     itemToRemove.ObjToStore = obj;

     ListOfStoreObjects.Remove(itemToRemove);

     return obj;
 }

4 个答案:

答案 0 :(得分:3)

您需要实现通用IEquatable<T>集合在内部使用的List<T>来确定自定义类型的相等性。

以下是一个示例(给定ID是您唯一的标识符):

public class MyClass : IEquatable<MyClass>
{
    public string ID { get; set; }
    public myEnum CallType { get; set; }
    public object ObjToStore { get; set; }

    public bool Equals(MyClass x)
    {
        return x.ID.Equals(this.ID);
    }
}

More about the interface.

修改

您创建一个新对象,该对象不会与您尝试删除的对象共享引用相等性。上面提供的方法可以解决问题,但它不是您案例中最干净的解决方案。

我建议您index删除,只有当您非常喜欢使用List代替HashSet时才会删除:

 for(int i = 0; i < ListOfStoreObjects.Count; i++)
 {
     if( ListOfStoreObjects[i].ID == id && ListOfStoreObjects[i].CallType == callType)
     {
         ListOfStoreObjects.RemoveAt(i);
         break;
     }
 }

为什么RemoveAt代替RemoveArray作为List的基础集合,按索引查找元素O(1),因此对于这种类型的集合,由于数组如何解析语义,它是最有效的删除项的方法在记忆中。 此外,如果您查看.NET源Remove方法将再次通过collection循环并删除元素调用Equals方法以检查相等性。

答案 1 :(得分:1)

您正在错误地删除对象。你必须像这样删除它:

public MyClass RetrieveObj(string id, myEnum callType)
{
     MyClass obj = null;

     foreach(var element in ListOfStoreObjects)
     {
         if( element.ID == id && element.CallType == callType)
         {
             obj = element;
             break;
         }
     }
     ListOfStoreObjects.Remove(obj);

     return obj;
}

这是一个非常常见的错误。您正在找到正确的对象,而不是使用该实例,而是创建一个新的对象,该对象将永远与列表中的任何对象匹配。

替代解决方案

分享一个更简单的单行方式来做你想做的事情:

ListOfStoreObjects.RemoveAll(x => x.ID == id && x.CallType == callType);

答案 2 :(得分:0)

理想情况下Remove()应该有效,并且是更好,更正确的方法。你应该试着找出你没有正确使用它的原因。但如果你仍然无法尝试这样的事情。您应该将st.IsCompleted替换为其他条件,以指示该项目将被删除。请注意,这不如Remove()有效,仅用作解决方法。

ListOfStoreObjects = ListOfStoreObjects.Where(st => st.IsCompleted).ToList();

答案 3 :(得分:0)

由于您在调用MyClass时创建了List<T>.Remove()的新实例,因此您必须实施IEquatable<T>来告诉Remove比较ID(以及其他属性)查找要删除的集合项时只是对象引用

IEquatable<T>中实施MyClass界面:

public class MyClass : IEquatable<MyClass>
{
    public string ID { get; set; }
    public myEnum CallType { get; set; }
    public object ObjToStore { get; set; }

    public bool Equals(MyClass other)
    {
        return other != null && other.ID == this.ID;
    }
}

来自List<T>.Remove documentation

  

如果类型T实现IEquatable泛型接口,则相等   comparer是该接口的Equals方法;否则,   default equality comparer是Object.Equals。