比较未知对象类型时,如何确保对字符串进行不区分大小写的比较?
How to ensure case insensitive comparison on strings when comparing unknown object types?
我有一个 DataGridView,我正在编写一些通用代码来添加过滤器。列的基础数据类型可以是任何类型,但是如果它们是字符串,我希望过滤器使用不区分大小写的比较。
我还使用 Equals
方法而不是 ==
运算符来确保它不只是进行参考比较。字符串 Equals
方法有一个重载让你选择 StringComparison
类型,但我不知道它是否会是一个字符串所以我只能访问 Equals
object
.
可用的方法
我尝试为 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 只是具有一些属性的对象列表,例如您在下面看到的引用和项目是 IEnumerable<T>
.
foreach (var f in _filters)
{
items = items.Where(o => o[f.FieldName].Equals(f.Value, StringComparison.InvariantCultureIgnoreCase));
}
字符串比较位可以通过使用静态字符串 Equals 方法更简单:
return string.Equals(obj1.ToString(), obj2.ToString(), comparisonType);
- 您已经对 obj1 和 obj2 进行了空检查
- 将 obj1 转换为字符串实际上并不是将其转换为字符串,它只是意味着编译器允许您在其上使用类似字符串的方法。
编辑:为清楚起见,这将是我的完整静态方法:
public static class ObjectHelper
{
public static bool EqualStrings(object obj1, object obj2, StringComparison comparisonType)
{
return string.Equals(obj1?.ToString(), obj2?.ToString(), comparisonType);
}
}
我个人不会在对象上使用扩展方法 - 它会污染您的智能感知。为了简洁起见,我会使用 null 检查运算符。
您可以使用其他扩展方法,例如 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;
}
}
我有一个 DataGridView,我正在编写一些通用代码来添加过滤器。列的基础数据类型可以是任何类型,但是如果它们是字符串,我希望过滤器使用不区分大小写的比较。
我还使用 Equals
方法而不是 ==
运算符来确保它不只是进行参考比较。字符串 Equals
方法有一个重载让你选择 StringComparison
类型,但我不知道它是否会是一个字符串所以我只能访问 Equals
object
.
我尝试为 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 只是具有一些属性的对象列表,例如您在下面看到的引用和项目是 IEnumerable<T>
.
foreach (var f in _filters)
{
items = items.Where(o => o[f.FieldName].Equals(f.Value, StringComparison.InvariantCultureIgnoreCase));
}
字符串比较位可以通过使用静态字符串 Equals 方法更简单:
return string.Equals(obj1.ToString(), obj2.ToString(), comparisonType);
- 您已经对 obj1 和 obj2 进行了空检查
- 将 obj1 转换为字符串实际上并不是将其转换为字符串,它只是意味着编译器允许您在其上使用类似字符串的方法。
编辑:为清楚起见,这将是我的完整静态方法:
public static class ObjectHelper
{
public static bool EqualStrings(object obj1, object obj2, StringComparison comparisonType)
{
return string.Equals(obj1?.ToString(), obj2?.ToString(), comparisonType);
}
}
我个人不会在对象上使用扩展方法 - 它会污染您的智能感知。为了简洁起见,我会使用 null 检查运算符。
您可以使用其他扩展方法,例如 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;
}
}