Possible to create case insensitive string class?

2019-07-09 05:05发布

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?

3条回答
Emotional °昔
2楼-- · 2019-07-09 05:23

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

查看更多
劫难
3楼-- · 2019-07-09 05:27

Building on type of deathismyfriend's answer above, I would extend the string class:

public static class StringExtensions
{
    public static int CaseInsensitveCompare(this string s, string stringToCompare)
    {
        return String.Compare(s, stringToCompare, StringComparison.InvariantCultureIgnoreCase);
    }
}

And the call:

int result = firstString.CaseInsensitveCompare(secondString);
查看更多
手持菜刀,她持情操
4楼-- · 2019-07-09 05:47

Comparing string is rather easy. You can simply use the equals method or the compare method.

Example:

string s = "A";
s.Equals("a", StringComparison.InvariantCultureIgnoreCase); // Will return true.

string s = "A";
s.Equals("a", StringComparison.InvariantCulture); // Will return false.

You should also look at this. That will explain a little more on comparing strings.

查看更多
登录 后发表回答