为什么这个程序打印"未添加"而我认为它应该打印"添加"?
using System;
using System.Collections.Generic;
class Element
{
public int id;
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
Element ret = new Element(d);
return ret;
}
public static bool operator ==(Element e1, Element e2)
{
return (e1.id == e2.id);
}
public static bool operator !=(Element e1, Element e2)
{
return !(e1.id == e2.id);
}
}
class MainClass
{
public static void Main(string[] args)
{
List<Element> element = new List<Element>();
element.Add(2);
if(element.Contains(2))
Console.WriteLine("added");
else
Console.WriteLine("not added");
}
}
Run Code Online (Sandbox Code Playgroud)
该Contains方法不使用==运算符.问题是什么?
Jon*_*eet 57
Contains方法不使用==运算符
不 - 它使用Equals,你没有覆盖...所以你得到的默认行为Equals,即检查参考标识.你应该覆盖Equals(object)并GetHashCode保持彼此一致 - 为了理智,与你的==过载一致.
我还建议实施IEquatable<Element>,List<Element>优先使用Equals(object),作为EqualityComparer<T>.Default适当的选择.
哦,你的运算符重载也应该处理空引用.
我也强烈建议使用私有字段而不是公共字段,并使您的类型不可变 - 密封它并使idreadonly.实现可变类型的相等可能导致奇怪的情况.例如:
Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!
Run Code Online (Sandbox Code Playgroud)
这会发生,因为哈希代码会改变(至少在大多数实现中),因此字典下的哈希表甚至无法找到对已存在的同一对象的引用.
所以你的课程看起来像这样:
internal sealed class Element : IEquatable<Element>
{
private readonly int id;
public int Id { get { return id; } }
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
return new Element(d);
}
public static bool operator ==(Element e1, Element e2)
{
if (object.ReferenceEquals(e1, e2))
{
return true;
}
if (object.ReferenceEquals(e1, null) ||
object.ReferenceEquals(e2, null))
{
return false;
}
return e1.id == e2.id;
}
public static bool operator !=(Element e1, Element e2)
{
// Delegate...
return !(e1 == e2);
}
public bool Equals(Element other)
{
return this == other;
}
public override int GetHashCode()
{
return id;
}
public override bool Equals(object obj)
{
// Delegate...
return Equals(obj as Element);
}
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一下,我不确定隐式转换的优点 - 我通常会远离那些,我自己.)
Eri*_* J. 12
Contains方法不使用==运算符.问题是什么?
那是正确的.
此方法[Contains]通过使用默认的相等比较器来确定相等性,由对象的T的IEquatable.Equals方法的实现(列表中的值的类型)定义.
http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx
您还需要覆盖Equals().注意当重载Equals()时,几乎总是正确地重写GetHashCode().
覆盖Equals和GetHashCode喜欢:
class Element
{
public int id;
protected bool Equals(Element other)
{
return id == other.id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Element) obj);
}
public override int GetHashCode()
{
return id; //or id.GetHashCode();
}
//..... rest of the class
Run Code Online (Sandbox Code Playgroud)
此方法通过使用默认的相等比较器来确定相等性,由对象的
IEquatable<T>.EqualsT方法实现(列表中的值类型)定义.
| 归档时间: |
|
| 查看次数: |
16118 次 |
| 最近记录: |