4

Throughout our codebase we have 311 of the following cases:

string.Equals(stringA, stringB, StringComparison.CurrentCultureIgnoreCase);

Using StringComparison.CurrentCultureIgnoreCase accounts for like 99% of all string.Equals references.

I can't override either of these because System.String is a sealed class.

public static bool Equals(string a, string b)
public static bool Equals(string a, string b, StringComparison comparisonType)

Is the only option here to create a new static implementation like:

public static class StringComparer
{
  public static bool Equals(string a, string b)
  {
     return string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
  }
}

Instead of writing the first code sample everywhere, is there a way to set CurrentCultureIgnoreCase as the default way of comparing strings ?

mjwills
  • 23,389
  • 6
  • 40
  • 63
Zze
  • 18,229
  • 13
  • 85
  • 118
  • I don't understand the question. If you are asking how to change `CurrentCultureIgnoreCase` then global search and replace is what I'd suggest. – mjwills Jul 31 '19 at 00:36
  • 2
    @mjwills I think Zze means that rather than writing the first code sample _everywhere_, is there a way to set `CurrentCultureIgnoreCase` as the default way of comparing strings. – ProgrammingLlama Jul 31 '19 at 00:37
  • @John that is correct. I have updated the question with your clarification. – Zze Jul 31 '19 at 00:38
  • 1
    No, that isn't possible. I'd suggest writing your own extension method called `EqualsIgnoreCase`. – mjwills Jul 31 '19 at 00:38

1 Answers1

4

Create an extension method (which does work with null arguments).

I named it Eq for brevity (but kept it internal so it doesn't confuse external consumers of your code)

internal static class StringExtensions
{
    /// <summary>Performs a <see cref="StringComparison.CurrentCultureIgnoreCase"><c>CurrentCultureIgnoreCase</c></see> equality check.</summary>
    public static Boolean Eq( this String x, String y )
    {
        return String.Equals( x, y, StringComparison.CurrentCultureIgnoreCase );
    } 
}

Used like so:

if( stringX.Eq( stringY ) ) {

} 

Extension methods also work with null values without throwing a NullReferenceException:

String x = null;
String y = null;
if( x.Eq( y ) )
{
    // this will run without exceptions
}

For C# 8.0+ and latter with nullable-reference-types, you can improve the method with attributes, for example:

using System.Diagnostics.CodeAnalysis;

internal static class StringExtensions
{
    /// <summary>Performs a <see cref="StringComparison.CurrentCultureIgnoreCase"><c>CurrentCultureIgnoreCase</c></see> equality check.</summary>
    [returns: NotNullIfNotNull("x")]
    public static Boolean? Eq(
        this String? x,
        String? y
    )
    {
        if( x is null ) return null;
        return String.Equals( x, y, StringComparison.CurrentCultureIgnoreCase );
    } 
}

Or:

using System.Diagnostics.CodeAnalysis;

internal static class StringExtensions
{
    /// <summary>Performs a <see cref="StringComparison.CurrentCultureIgnoreCase"><c>CurrentCultureIgnoreCase</c></see> equality check. Always returns false when <param ref="x"/> is null.</summary>
    public static Boolean Eq(
        [NotNullWhen(true)] this String? x,
        [NotNullWhen(true)] String? y
    )
    {
        if( x is null ) return false;
        return String.Equals( x, y, StringComparison.CurrentCultureIgnoreCase );
    } 
}

That way the compiler can use this Eq method to also determine the null-state of x (assuming you're okay with null.Eq( null ) == false, just like in SQL):

String? x = "foo" // or `null`;
String? y = "bar" // or `null`;
if( x.Eq( y ) )
{
    SomeMethodThatRequiresNonNullArgs( x ); // the compiler knows `x` and `y` are non-null here. 
}
Dai
  • 141,631
  • 28
  • 261
  • 374