如何检查泛型对象是否相等,适用于字符串

本文关键字:是否 字符串 适用于 对象 泛型 何检查 检查 | 更新日期: 2023-09-27 18:13:22

我今天在重构一些代码时遇到了一些非常奇怪的行为。

我有一些代码看起来像这样:

    private AType Blah
    {
        get
        {
            return (from something in AList
                    where _x == null || something.x == _x
                    where _y == null || something.y == _y
                    where _z == null || something.z.IsSameAs(_z)
                    select something).Single();
        }
    }

我已经匿名了类型和变量名,因为它们对问题不重要。

_x和其他东西的类型。X是字符串,然后是_y之类的。Y是一个引用类型。同样的,_z和。Z是具有值比较的引用类型。

我想我可以这样做:

    public AType Blah
    {
        get { return AList.Single(something => DetailsMatch(something.x, something.y, something.z)); }
    }
    private bool DetailsMatch(string x, AnotherType y, AFurtherType z)
    {
        return NullOrCheck(_x, x) &&
               NullOrCheck(_y, y) &&
               NullOrCheck(_z, z.IsSameAs);
    }
    private bool NullOrCheck<T>(T value, T expected) where T : class
    {
        return NullOrCheck(value, v => v == expected);
    }
    private static bool NullOrCheck<T>(T value, Func<T,bool> check) where T : class
    {
        return value == null || check(value);
    }

这一切似乎都有意义,但令我惊讶的是,一些测试开始失败。结果是,使用==操作符时,相同的字符串(例如"1A04"answers"1A04")不再被认为是相等的。

看了下面的't操作符==可以应用于c#中的泛型类型吗?这两个字符串似乎是在引用相等的基础上进行比较的,而不是以正常的方式进行比较。

在c#中是否有一种安全的方法来做到这一点,或者在泛型方法中使用==是否应该被认为是危险的?

只是为了确认这是问题,我的修复包括在字符串情况下内联有问题的方法,结果是:

    private bool DetailsMatch(string x, AnotherType y, AFurtherType z)
    {
        return (_x == null || _x == x) &&
               NullOrCheck(_y, y) &&
               NullOrCheck(_z, z.IsSameAs);
    }

嘿,马上-一切正常,测试再次通过

如何检查泛型对象是否相等,适用于字符串

您可以使用Object.Equals:

return NullOrCheck(value, v => object.Equals(v, expected));

string类重载静态==操作符来比较它的两个字符串参数是否相等,即

string first = "abc";
string second = "abc";
bool eq = first == second;

调用==将使用重载的==作为字符串,因为firstsecond的静态类型都是string

然而,

object first = "abc";
object second = "abc";
bool eq = first == second;

使用的==操作符将是object定义的操作符,因为firstsecond的静态类型是object。请注意,在这种情况下,由于字符串实习,firstsecond实际上包含对同一个字符串的引用,但通常情况并非如此。

在泛型方法中,==将解析为为object定义的静态==,而不是为string定义的更具体的版本。由于==object s的简单引用相等性检查,因此其行为不同。

Equals方法是虚拟的,可以覆盖它来专门化自定义类型的相等性检查。因此,在

object first = "abc";
object second = "abc";
bool eq = first.Equals(second);

将调用string.Equals方法,检查字符串是否具有相同的值,而不仅仅是相同的引用。

静态object.Equals方法使用虚拟Equals实例方法,因此它也将检查字符串是否具有相同的值,而不仅仅是指向相同的字符串实例。静态object.Equals也检查其参数是否为null,因此比直接调用objA.Equals(objB)更安全。