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项)
内部使用方法检查对象是否相等。因此,如果您想将methodList.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非常有趣的一点是,如果类不是密封的
,那么精确的类型匹配就很重要了。我从未想过比较基类和派生类的可能性。