我遇到一个问题,即使包含在列表中,contains方法也将返回false。有人可以告诉我这是怎么回事吗?
Program.CS
points.Add(new Point(-4, -7));
points.Add(new Point(0, 0));
points.Add(new Point(1, 2));
points.Add(new Point(-4, 5));
points.Insert(2, new Point(3, 1));
points.Add(new Point(7, -2));
points[0] = new Point(2, 1);
points.RemoveAt(2);
bool returnPoint = false;
returnPoint = points.Contains(new Point(1, 2));
PointList.CS
public bool Contains(Point item)
{
return _Points.Contains(item);
}
Point.CS
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
答案 0 :(得分:3)
由于Point
是一个类,因此它是一个引用类型。默认情况下,引用类型检查引用相等性。如果要获得期望的行为,则应覆盖Equals
中的GetHashCode
和Point
方法,并且在执行IEquatable<Point>
时可能不会受到伤害您正在使用==
和!=
运算符。
示例实现如下:
public class Point : IEquatable<Point>
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public bool Equals(Point other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return X == other.X && Y == other.Y;
}
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((Point)obj);
}
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Y;
}
}
public static bool operator ==(Point left, Point right)
{
return Equals(left, right);
}
public static bool operator !=(Point left, Point right)
{
return !Equals(left, right);
}
}
如果看起来很多,那就是。不幸的是,实现平等往往需要在C#中使用大量的样板。如果我们在C#8中获得了Record类型,那么可能会减轻一些痛苦,但这是典型的方法。
答案 1 :(得分:1)
包含在ArrayList
中的对象在对象上使用Equals()
的实现。当前,您正在检查对象引用是否相等。
Point point = new Point(5, 2);
Point refPoint = point; // refer to same object
points.Add(point);
bool returnPoint = false;
returnPoint = points.Contains(refPoint); // return true
对于引用类型,需要在您的课程中覆盖Equals()
和GetHashcode
:
public override bool Equals(object other) {
Point otherPoint = other as Point;
if(otherPoint != null)
return (X.Equals(otherPoint.X) && (Y.Equals(otherPoint.Y)));
return false;
}
答案 2 :(得分:1)
点是引用类型,因此您无意间比较了引用,而不是属性。
您可以使用LINQ的Any()
比较属性,并传递一个执行所需比较的lambda表达式。
//using System.Linq;
returnPoint = points.Any( p => p.X == 1 && p.Y == 2 );
答案 3 :(得分:0)
您需要valueObject作为最佳实践解决方案,而为了进行比较,仅x和y可能不需要。您应该将功能流程视为DDD设计 look here
public abstract class ValueObject
{
protected static bool EqualOperator(ValueObject left, ValueObject right)
{
if (ReferenceEquals(left, null) ^ ReferenceEquals(right, null))
{
return false;
}
return ReferenceEquals(left, null) || left.Equals(right);
}
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
{
return !(EqualOperator(left, right));
}
protected abstract IEnumerable<object> GetAtomicValues();
public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (ValueObject)obj;
var thisValues = GetAtomicValues().GetEnumerator();
var otherValues = other.GetAtomicValues().GetEnumerator();
while (thisValues.MoveNext() && otherValues.MoveNext())
{
if (ReferenceEquals(thisValues.Current, null) ^ ReferenceEquals(otherValues.Current, null))
{
return false;
}
if (thisValues.Current != null && !thisValues.Current.Equals(otherValues.Current))
{
return false;
}
}
return !thisValues.MoveNext() && !otherValues.MoveNext();
}
public override int GetHashCode()
{
return GetAtomicValues()
.Select(x => x != null ? x.GetHashCode() : 0)
.Aggregate((x, y) => x ^ y);
}
}
您的PointList.cs
public class PointList
{
public string Bla { get; set; }
public List<Point> Points { get; protected set; } = new List<Point>();
public void AddPoint(int x, int y)
{
AddPoint(new Point(x, y));
}
public void AddPoint(Point p)
{
if (!Points.Any(x => x.Equals(p)))
Points.Add(p);
}
public void RemovePoint(int x, int y)
{
RemovePoint(new Point(x, y));
}
public void RemovePoint(Point point)
{
Points.Remove(point);
}
public Point GetPoint(int x, int y)
{
return GetPoint(new Point(x, y));
}
public Point GetPoint(Point point)
{
return Points.FirstOrDefault(x => x.Equals(point));
}
}
您的Point.cs
public class Point : ValueObject
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
protected override IEnumerable<object> GetAtomicValues()
{
yield return X;
yield return Y;
}
}
示例
class Program
{
static void Main(string[] args)
{
var list = new PointList();
list.AddPoint(1, 1);
list.AddPoint(1, 2);
list.AddPoint(14, 53);
list.RemovePoint(1, 1);
list.RemovePoint(new Point(1, 2));
var p2 = list.GetPoint(14, 53);
var p1 = list.GetPoint(new Point(14, 53));
}
}