Search code examples
c#.netstringclasscase-insensitive

Possible to create case insensitive string class?


What would be required to create a case-insensitive string type that otherwise behaves exactly like a string?

I've never heard of anyone making a case insensitive string type like this and it's obviously not part of the framework, but it seems like it could be very useful. The fact that SQL does case insensitive comparisons by default is a great case in point. So I'm thinking it's either not possible, or else there's a really good reason why no one does it that I'm not aware of.

I know it would require using an implicit operator for assignment, and you would have to override the equals operator. And for overriding GetHashCode(), I'm thinking you could just return ToLower().GetHashCode().

What am I missing?


Solution

  • It wouldn't behave "exactly like a string". The string type is special and is baked into the language spec. C# strings exhibit special behavior, such as

    • being a reference type, that gets passed by value. Reference types are normally passed by...well...reference.

    • are interned by default. That means that there is only ever a single instance of a given string. The following code results in the creation of just a single string: a, b and c all point to exactly the same instance of the string quick. That means that Object.ReferenceEquals() is true when comparing any two:

      string a = "The quick brown dog...".Substring(4,5) ;
      string b = new string(new char[]{'q','u','i','c','k'});
      string c = new StringBuilder().
                 .Append('q')
                 .Append('u')
                 .Append('i')
                 .Append('c')
                 .Append('k')
                 .ToString()
                 ;
      

    [edited to note: while one might think that this should be possible, a little fiddling around suggests that one can't actually create a custom implementation/subtype of CompareInfo as it has no public constructors and its default constructor is internal. More in the answers to this question: Globally set String.Compare/ CompareInfo.Compare to Ordinal

    Grrr...]

    What you could do is this:

    String comparisons are done using the current culture's collation/comparison rules. Create a custom culture for your app, say, a copy of the the US culture that uses the collation/comparison rules you need. Set that as the current culture and Bob's-yer-uncle.

    You'll still get compiler/ReSharper whines because you're doing string comparisons without specifying the desired comparison semantics, but your code will be clean.

    For more details, see