在比较未知对象类型时,如何确保字符串的比较不区分大小写?

How to ensure case insensitive comparison on strings when comparing unknown object types?

提问人:BVernon 提问时间:2/6/2020 最后编辑:Reza AghaeiBVernon 更新时间:2/6/2020 访问量:371

问:

我有一个 DataGridView,我正在编写一些通用代码来添加过滤器。列的基础数据类型可以是任何类型,但是如果它们是字符串,我希望过滤器使用不区分大小写的比较。

我还使用该方法而不是运算符来确保它不仅仅是进行参考比较。string 方法有一个重载,可以让你选择一个类型,但我不知道它是否会是一个字符串,所以我只能访问一个 .Equals==EqualsStringComparisonEqualsobject

我尝试编写一个扩展方法,让我指定一个类型。这个想法是,如果对象是字符串,那么它将在字符串对象上调用适当的重载,但除此之外,它只会使用普通方法。但是,这似乎不起作用,因为我收到一个编译错误,指出我无法将该方法作为实例方法访问,并且必须指定类型。我在下面包含了扩展方法,以防万一我在其中做错了什么......我确实匆匆写了它,但我认为这不是问题所在;我想我必须找到另一种方法来做到这一点。EqualsobjectStringComparisonEqualsEquals

public static class Extensions
{
    public static bool Equals(this object obj1, object obj2, StringComparison comparisonType)
    {
        if (obj1 == null && obj2 == null)
            return true;
        if (obj1 == null && obj2 != null)
            return false;
        if (obj1 != null && obj2 == null)
            return false;

        string s = obj1 as string;

        if (s != null)
        {
            var s2 = obj2 as string;
            return s2 != null && s.Equals(s2, comparisonType);
        }
        else
            return obj1.Equals(obj2);
    }
}

所以我正在寻找更好的方法,或者如果我只是在上面的代码中犯了一个错误,请告诉我。

编辑:

下面也是使用代码的样子。_filters只是一个对象列表,其中包含一些属性,例如您在下面看到的引用和 items 是 。IEnumerable<T>

        foreach (var f in _filters)
        {
            items = items.Where(o => o[f.FieldName].Equals(f.Value, StringComparison.InvariantCultureIgnoreCase));
        }
C# .NET 字符串 对象 比较

评论

0赞 BVernon 2/6/2020
是的,扩展方法可以正常编译。这是我刚刚添加的 EDIT 中的代码无法编译。
1赞 Reza Aghaei 2/6/2020
使用另一个扩展方法,例如,在方法中检查参数是否为字符串,以您喜欢的方式进行比较。IsEqual
0赞 BVernon 2/6/2020
@RezaAghaei 做到了。为自己没有想到而感到愚蠢。谢谢!
0赞 TheGeneral 2/6/2020
如果此方法是多余的,则大多数
1赞 BVernon 2/6/2020
@MichaelRandall 当然,但是我以这种方式编写所花费的时间更少,它很简单,而且它的性能与您为我将使用它的任何目的编写的完美内容一样好。:D

答:

0赞 Kurt Hamilton 2/6/2020 #1

通过使用静态字符串 Equals 方法,字符串比较位可以简单得多:

return string.Equals(obj1.ToString(), obj2.ToString(), comparisonType);
  1. 您已经对 obj1 和 obj2 进行了空检查
  2. 将 obj1 转换为字符串实际上并不是将其转换为字符串,它只是意味着编译器允许您在其上使用类似字符串的方法。

编辑:为清楚起见,这将是我的完整静态方法:

public static class ObjectHelper
{
    public static bool EqualStrings(object obj1, object obj2, StringComparison comparisonType)
    {
        return string.Equals(obj1?.ToString(), obj2?.ToString(), comparisonType);
    }
}

我个人不会对对象进行扩展 - 它会污染你的智能感知。为了简洁起见,我会使用 null 检查运算符。

评论

0赞 BVernon 2/6/2020
它只会污染我在 using 部分中具有相关命名空间的地方。此解决方案如何处理对象不是字符串的情况?如果我知道这是一个字符串,那么正如你所说,我什至不会为扩展方法而烦恼。但是我需要它表现得恰到好处,无论是字符串还是其他数据类型。
0赞 BVernon 2/6/2020
此外,“污染”完全不会打扰我。如果你明白我的意思,我更多的是完成工作,而不是确保我的车间干净。
0赞 Kurt Hamilton 2/6/2020
这。ToString() 方法使它成为字符串。如果使用的是自定义对象,则可以重写所有对象附带的 ToString 方法,以提供应表示该类的任何字符串。
0赞 Kurt Hamilton 2/6/2020
啊,我没有从你的问题中得到你想对字符串使用字符串比较,否则回退到对象相等。
1赞 Reza Aghaei 2/6/2020 #2

您可以使用其他扩展方法,例如 ,然后在方法内检查参数是否为字符串,以您喜欢的方式进行比较。IsEqual

例如,类似于以下代码的内容。我还没有测试功能,它只是演示了这个想法:

public static class ObjectExtesions
{
    public static bool IsEqual(this object left, object right)
    {
        if (left == null && right == null)
            return true;
        if (left != null && right != null)
        {
            if (left is string && right is string)
                return ((string)left).Equals((string)right,
                    StringComparison.InvariantCultureIgnoreCase);
            else
                return left.Equals(right);
        }
        return false;
    }
}

评论

0赞 Reza Aghaei 2/6/2020
@PrasadTelkikar虽然代码只是一个示例来演示这个想法,但要回答您的问题,是的,我们需要进行 null 检查,因为→如果 left 是 null 字符串,它会抛出异常。left.Equals(right)
1赞 Reza Aghaei 2/6/2020
如何让它更轻松或更优雅?看看这篇文章,了解使用 Dynamic LINQ 或 Dynamic Lambda 表达式的一些想法: 根据单元格值筛选 datagridview 中的对象列表
0赞 Reza Aghaei 2/6/2020
不要错过链接的帖子。它有点长,但它很可能会有所帮助。您只需要考虑选项 1 和选项 2。
0赞 BVernon 2/6/2020
谢谢,我实际上有一些很久以前写的自定义滚动代码,这对我有很大帮助。它使用一些反射来处理属性,我有一个支持过滤和排序的列表,但我只是想更新过滤器比较以支持这一点。
1赞 Reza Aghaei 2/6/2020
凉!您更了解自己的要求。只是想分享一些可能对:)有所帮助的东西