元组可以存放不同类型的数据,同时不需要额外地声明类。有时候我们需要对元组进行比较。以确定元给是否相同。由于元组的特殊性,它是值类型的。因此如下的代码不是我们期望的结果。
var a = Tuple.Create<string, int>("abc", 1);
var b = Tuple.Create<string, int>("abc", 1);
if (a==b)//因为a和b引用了不同的对象,所以它返回false.
{
Console.WriteLine("相同");
}
在程序中运行上述代码的时候不会输出“相同”字符。这是因为它是值类型的。比较器认为a 和 b 是不同的对象,因此不返回true的结果。
那么 怎么才能实现对它们的内容进行比较呢:答案是使用Equals
var a = Tuple.Create<string, int>("abc", 1);
var b = Tuple.Create<string, int>("abc", 1);
if (a .Equals(b))
{
Console.WriteLine("Equals方法比较");
}
上述代码会对Tuple的每一项进行比较,并返回true.如果将1改成2,那么就会返回false.
有时候,我们可能只需要对元组中的某一些项目进行比较,如果它们相同。我们就认为它们是同一个东西。那么 我们就需要建立一个特殊的比较器了。
class TupleComparer : System.Collections.IEqualityComparer
{
public new Boolean Equals( object x, object y)
{
//因为比较器会对元组的第一个组成部份调用一次比较器,因此类型x依次为此例的abc,123.
//所以为了实现只针对元组中的某一些部分进行比较,确认它们为一种,就需要避免不相关的项的比较。
if (x.GetType().Equals(typeof(string)))
{
if (x.Equals(y))
{
return true;
}
return false;
}
return true;
}
public int GetHashCode(object x)
{
return ((Tuple<string, int>)x).Item1.GetHashCode();
}
}
这里须要注意的是,比较器会针对元组的每一项目调用一次比较器。如元组包括三项内容,那么比较器会被调用三次。因此不能将比较器的Equals方法内写如下代码 var X = x as Tuple<string, int>;实际上object x 依次为'abc',1将它转为元给一直是为null。我开始就范了这样的错误。上述代码表示:只要第一项相同,那么这个元组就相同。
使用比较器代码如下:
var a = Tuple.Create<string, int>("abc", 1);
var b = Tuple.Create<string, int>("abc", 2);
if ((a as System.Collections.IStructuralEquatable ).Equals(b,new TupleComparer()))
{
Console.WriteLine("Equals实现特定的比较");
}
由于元组使用了两个方式调用Equals,一个是object方法,调用如上一个所述。一个是使用System.Collections.IStructuralEquatable 接口。由于它是显示的。因此要明确转换为System.Collections.IStructuralEquatable 接口。只有这样,才能代入比较参数new TupleComparer().到此,就实现了只对元组待定内容进行比较的方法了。