C# 查看如果列表<;T>;有<;T>;(不考虑<;T>;中的属性顺序)在C中#

C# 查看如果列表<;T>;有<;T>;(不考虑<;T>;中的属性顺序)在C中#,c#,list,C#,List,我有移动列表 ListOfMoves.Add(new Moves() { int position1= number1, int position2= number2, }); 现在,我想检查ListOfMoves是否包含例如Move(2,3),还想检查它是否包含Move(3,2)。 我尝

我有
移动列表

 ListOfMoves.Add(new Moves()
                        {
                           int position1= number1,
                            int position2= number2,
                        });
现在,我想检查
ListOfMoves
是否包含例如
Move(2,3)
,还想检查它是否包含
Move(3,2)

我尝试了
if(ListOfMoves.Contains(new Move(2,3))
,但这无法正常工作。

显然无法工作,因为您无法比较实体本身,而必须使用
System.Linq与如下属性值进行比较

ListOfMoves.Where(x => x.position1 == 2 && x.position1 == 3)
注意:您发布的代码首先不应该编译

你说。。如果移动(3,2)或(2,3)在列表中,我需要得到true

然后使用
Any()
使用相同的谓词,如

if(ListOfMoves.Any(x => x.position1 == 2 && x.position1 == 3))
{
  // done something here
}

为此,您可以使用LINQ的任意函数。如果您想要位置[(2,3)或(3,2)]的两种组合,则需要在两次检查中通过两次

ListOfMoves.Any(x => 
    (x.position1 == 2 && x.position2 == 3) 
    || (x.position1 == 3 && x.position2 == 2) )
Any返回bool,这样您就可以将这行代码包装到if语句中,或者存储结果以供多次使用

潜在改进

如果你要做很多这些检查(你至少使用C版本7),你可以考虑一些小的重构,使用内置的元组类型:

这些举措将成为

public class Moves
{
    public (int position1, int position2) positions { get; set; }
}
ListOfMoves.Any(x => x.positions == (2,3) || x.positions == (3,2))
任何电话都会变成

public class Moves
{
    public (int position1, int position2) positions { get; set; }
}
ListOfMoves.Any(x => x.positions == (2,3) || x.positions == (3,2))
否则,在代码中,您仍然可以访问每个位置的基础值,如下所示:

ListOfMoves[0].positions.position1
显然,这取决于代码中的其他内容,因此完全取决于您

方法
列表。包含(T项)
内部使用方法检查对象是否相等。因此,如果您想将method
List.Contains(T item)
与您的类型
T
一起使用,以检查指定的
是否包含在
List
中,那么您需要覆盖类型
T
中的method
对象.Equals

重写
Object.Equals
时,还应重写
Object.GetHashCode
。这是一个很好的解释

下面是您应该如何在
Move
类中重写
Object.Equals
,以满足您的需求:

class Move
{
    public Move(int p1, int p2)
    {
        position1 = p1;
        position2 = p2;
    }

    public int position1 { get; }
    public int position2 { get; }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        if (ReferenceEquals(this, obj))
            return true;

        Move other = obj as Move;

        if (other == null)
            return false;

        // Here we specify how to compare two Moves. Here we implement your
        // requirement that two moves are considered equal regardless of the
        // order of the properties.
        return (position1 == other.position1 && position2 == other.position2) ||
               (position1 == other.position2 && position2 == other.position1);
    }

    public override int GetHashCode()
    {
        // When implementing GetHashCode we have to follow the next rules:
        // 1. If two objects are equal then their hash codes must be equal too.
        // 2. Hash code must not change during the lifetime of the object.
        //    Therefore Move must be immutable. (Thanks to  Enigmativity's usefull tip).
        return position1 + position2;
    }
}
当您重写
Object.Equals
时,您将能够使用条件
ListOfMoves.Contains(新移动(2,3))
来检查移动
Move(2,3)
Move(3,2)
是否包含在
ListOfMoves


下面是演示重写
对象的示例。等于

是否要使此
移动列表包含(新移动(2,3))
仅适用于类型
移动
或任何类型
T
?为什么不使用LINQ:
ListOfMoves.Any(m=>(m.position1==n1&&m.position2.==n2)|(m.position1==n2&&m.position2.==n1))
?您需要重写和/或实现
Move
类上的接口。
ListMoves.Any(Move=>Move.position1==number1&&Move.position2==number2)
将返回
true
,如果条件为
true
,则至少返回一项。使用Linq。正如@orhtej2指出的,您应该重写。转到此链接,查看如何在
Point
类中实现
Object.Equals
的示例。您的实现应该是相同的,但它必须考虑到属性的顺序并不重要。您必须重写
Equals
GetHashCode
。我知道它不可编译。我想告诉你这些位置是int类型的。如果Move(3,2)或(2,3)在列表中,我需要得到true,但是这段代码只检查位置1?我正在做点和框的游戏,我想检查线是否是长方形的,所以我必须检查8个移动,你只需要做一个or<代码>任意(x=>(x.position1==2&&x.position2==3)| |(position1==3&&x.position2==2))
@ScottChamberlain如果有任何元素,而不是两个元素,都是正确的。“显然它不起作用,因为您无法比较实体本身”-不,这并不明显——这就是OP询问的原因。哈希代码的第二条规则是它们不能在对象的生命周期内更改
Move
必须是不可变的。如果传递的对象不是
Move
实例,则实现将引发异常。考虑使用“<代码> > <代码>操作符。@ Enigmativity非常感谢您有用的提示。我把它添加到了帖子里。我还使类
Move
immutable.@orhtej2感谢您的评论。我不想使示例复杂化,因此没有包括类型检查和引用相等性检查。在您的评论之后,我决定包括这些检查。@orhtej2非常有趣的一点是,如果类不是
密封的
,那么精确的类型匹配就很重要了。我从未想过比较基类和派生类的可能性。