方法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;
}
答案 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);
}
}
修改强>
您创建一个新对象,该对象不会与您尝试删除的对象共享引用相等性。上面提供的方法可以解决问题,但它不是您案例中最干净的解决方案。
我建议您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
代替Remove
? Array
作为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。