2014-10-05 42 views
1

我创建了一个程序,在其中我有INT阵列的队列:当在队列中使用Contains时,控制台返回False。为什么?

Queue<int[]> Test = new Queue<int[]>(); 

鉴于阵列,我想要查询的阵列是否在队列内。

我目前使用的命名空间是:System,System.Collections和System.Collections.Generic。

我想是这样的:

Queue<int[]> Test = new Queue<int[]>(); 

Test.Enqueue(new int[] { 20, 20 }); 

Console.WriteLine(Test.Contains(new int[] { 20, 20 })); // Is the array {20,20} inside the queue? 

在这段代码中,在我看来,控制台会输出“真”,因为我加入了数组{20,20}到队列中,而现在我正在使用Contains方法进行检查。

但是当我运行代码 - 控制台输出false。

我有两个问题: 这是为什么发生?我该如何解决这个问题?

+0

比较适用于引用,您需要创建相等比较器或循环遍历每个数组并调用SequenceEqual并传递该新数组以进行比较。 – terrybozzio 2014-10-05 17:16:34

回答

3

因为数组是引用类型的比较将基于引用。即使内容相同,你的阵列也有不同的参考。这就是为什么你得到false

为了解决这个问题,你可以实现一个自定义比较,也可以使用LINQ方法,例如

bool arrayExists = Test.Any(x => x.SequenceEqual(new[] { 20, 20 })); 
+0

在正确的轨道上,但会为每个测试分配一个新的阵列。 – 2014-10-05 17:12:55

+0

是的,它可以通过在查询中创建数组来避免。 – 2014-10-05 17:15:05

1

Contains()使用该类型的默认比较器。对于数组,它比较数组引用,而不是内容。您将需要创建一个自定义的相等比较器。

像这样:

class ArrayComparer : IEqualityComparer<int[]> 
{ 
    public bool Equals(int[] x, int[] y) 
    { 
     return x.SequenceEqual(y); 
    } 

    public int GetHashCode(int[] obj) 
    { 
     int h = 0; 

     foreach (int item in obj) 
     { 
      h = (h << 5) + 3 + h^item.GetHashCode(); 
     } 

     return h; 
    } 
} 

Test.Contains(new int[] { 20, 20 }, new ArrayComparer()) 
0

数组由默认情况下,没有内容的参考比较。解决这个问题的一种方法是存储列表而不是数组,这将比较内容。您可以在添加到队列之前将您的阵列转换为列表,如果这很重要,可以在将它们取出后再次将其转换回列表。

相关问题