列表.包含奇怪的行为
本文关键字:包含奇 列表 | 更新日期: 2023-09-27 18:25:01
我不知道这里是否遗漏了什么,但奇怪的是,我下面的代码总是在List上引发异常。包含部分,尽管我确信列表包含元素:
using System;
using System.Linq;
using System.Collections.Generic;
class SomeClass
{
public string param1 {get; private set;}
public string param2 {get; private set;}
private SomeClass(){}
public SomeClass(string param1, string param2)
{
this.param1 = param1;
this.param2 = param2;
}
}
class SomeClass2
{
private List<SomeClass> myList = new List<SomeClass>();
public void Add(SomeClass someclass)
{
myList.Add(someclass);
}
public void Remove(SomeClass someClass)
{
// this part always rises an exception
if(!myList.Contains(someClass))
throw new System.ArgumentException("some error");
else myList.Remove(someClass);
}
}
class MainClass
{
public static void Main (string[] args)
{
var _someClass = new SomeClass2();
_someClass.Add(new SomeClass("aaa", "bbb"));
try
{
_someClass.Remove(new SomeClass("aaa", "bbb"));
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
引用Contains
方法的文档:
此方法通过使用默认相等来确定相等比较器,由对象的IEquatable(Of T)。T的Equals方法(列表中值的类型)。
因此,如果您希望Contains方法确定SomeClass
的两个实例是否相等,则可以在对象上实现IEquatable<T>
:
class SomeClass: IEquatable<SomeClass>
{
public string param1 { get; private set; }
public string param2 { get; private set; }
private SomeClass() { }
public SomeClass(string param1, string param2)
{
this.param1 = param1;
this.param2 = param2;
}
public bool Equals(SomeClass other)
{
return param1 == other.param1 && param2 == other.param2;
}
}
另一种可能性是实现自定义EqualityComparer<T>
:
class SomeClassEqualityComparer : IEqualityComparer<SomeClass>
{
private static readonly SomeClassEqualityComparer _instance = new SomeClassEqualityComparer();
public bool Equals(SomeClass x, SomeClass y)
{
return x.param1 == y.param1 && x.param2 == y.param2;
}
public int GetHashCode(SomeClass obj)
{
unchecked
{
int hash = 17;
hash = hash * 23 + obj.param1.GetHashCode();
hash = hash * 23 + obj.param2.GetHashCode();
return hash;
}
}
public static IEqualityComparer<SomeClass> Instance
{
get { return _instance; }
}
}
然后使用Contains方法的以下重载:
if (!myList.Contains(someClass, SomeClassEqualityComparer.Instance))
throw new System.ArgumentException("some error");
您没有删除SomeClass的同一个实例。这将起作用:
public static void Main ()
{
var _someClass = new SomeClass2();
var someClass = new SomeClass("aaa", "bbb");
_someClass.Add(someClass);
try
{
_someClass.Remove(someClass);
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
要使您的原始代码正常工作,您需要实现IEquatable。看见http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx.
很抱歉我没有花更多的时间在哈希代码实现上。我甚至不记得^是否是正确的xor运算符。。。我想我可以在xor之前腐烂13,但这似乎有点傻。
using System;
using System.Collections.Generic;
namespace DoesItCompile
{
class SomeClass
{
private object param1;
private object param2;
private SomeClass() { }
public SomeClass(string param1, string param2)
{
this.param1 = param1;
this.param2 = param2;
}
public override bool Equals(object oThat)
{
if (!(oThat is SomeClass))
return false;
SomeClass scThat = (SomeClass)oThat;
if (!string.Equals(this.param1, scThat.param1))
return false;
if (!string.Equals(this.param2, scThat.param2))
return false;
return true;
}
public override int GetHashCode()
{
return this.param1.GetHashCode() ^ this.param2.GetHashCode();
}
}
class SomeClass2
{
private List<SomeClass> myList = new List<SomeClass>();
public void Add(SomeClass someclass)
{
myList.Add(someclass);
}
public void Remove(SomeClass someClass)
{
// this part always rises an exception
if (!myList.Contains(someClass))
throw new System.ArgumentException("some error");
else myList.Remove(someClass);
}
}
class MainClass
{
public static void Main(string[] args)
{
var _someClass = new SomeClass2();
_someClass.Add(new SomeClass("aaa", "bbb"));
try
{
_someClass.Remove(new SomeClass("aaa", "bbb"));
Console.WriteLine("Have a nice president's day.");
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey();
}
}
}
附言-我不知道你为什么要问塞尔达的跟踪者,但我相信有充分的理由。