【问题标题】:How to ensure case insensitive comparison on strings when comparing unknown object types?比较未知对象类型时如何确保对字符串进行不区分大小写的比较?
【发布时间】:2020-02-06 07:48:43
【问题描述】:

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

我还使用Equals 方法而不是== 运算符来确保它不仅仅是进行参考比较。字符串Equals 方法有一个重载,可以让您选择StringComparison 类型,但我不知道它是否会成为字符串,所以我只能访问Equals 可用于@987654326 的方法@。

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

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 只是一个包含一些属性的对象列表,如下所示,item 是IEnumerable<T>

        foreach (var f in _filters)
        {
            items = items.Where(o => o[f.FieldName].Equals(f.Value, StringComparison.InvariantCultureIgnoreCase));
        }

【问题讨论】:

  • 是的,扩展方法编译得很好。我刚刚添加的 EDIT 中的代码无法编译。
  • 使用其他扩展方法,如IsEqual,在方法内部检查参数是否为字符串,以您喜欢的方式进行比较。
  • @RezaAghaei 做到了。因为自己没有想到它而感到愚蠢。谢谢!
  • 如果这种方法是多余的,大多数情况下
  • @MichaelRandall 当然,但是我用这种方式写的时间更少,它很简单,而且它的性能与你为任何我将使用它的目的编写的完美一样。 :D

标签: c# .net string object comparison


【解决方案1】:

您可以使用其他扩展方法,例如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;
    }
}

【讨论】:

  • @PrasadTelkikar 虽然代码只是演示该想法的示例,但要回答您的问题,是的,我们需要进行空检查,因为 left.Equals(right) → 如果 left 为空字符串,它将引发异常.
  • 什么让它更容易或更优雅?看看这篇文章以了解使用动态 linq 或动态 lambda 表达式的一些想法:Filtering list of objects in datagridview based on cell value
  • 不要错过链接的帖子。它有点长,但很可能会有所帮助。您只需要考虑选项 1 和选项 2。
  • 谢谢,实际上我有一些我很久以前写的自定义滚动代码可以帮助解决这个问题。它使用一些反射来处理属性,我有一个支持过滤和排序的列表,但我只是想更新过滤器比较以支持这一点。
  • 酷!你更了解你的要求。只是想分享一些可能有帮助的东西:)
【解决方案2】:

使用静态字符串 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);
    }
}

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

【讨论】:

  • 它只会污染我在 using 部分中有相关命名空间的地方。该解决方案如何处理对象不是字符串的情况?如果我知道它是一个字符串,那么正如你所说,我什至不会使用扩展方法。但无论是字符串还是其他数据类型,我都需要它的行为适当。
  • “污染”也完全不会打扰我。如果你明白我的意思,我更关心的是完成工作,而不是确保我的车间干净。
  • .ToString() 方法使它成为一个字符串。如果您使用自定义对象,则可以覆盖所有对象附带的 ToString 方法,以提供应代表该类的任何字符串。
  • 啊,我没有从你的问题中得到你想对字符串使用字符串比较,否则回退到对象相等。
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
相关资源
最近更新 更多