如果列表中存在则包含返回的False

时间:2018-10-05 00:47:16

标签: c#

我遇到一个问题,即使包含在列表中,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;
}

4 个答案:

答案 0 :(得分:3)

由于Point是一个类,因此它是一个引用类型。默认情况下,引用类型检查引用相等性。如果要获得期望的行为,则应覆盖Equals中的GetHashCodePoint方法,并且在执行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));


        }
    }