-12

How would I override the behavior of the == operator in order to do case insensitive comparisons?

var areSame = "alex" == "ALex";

I want areSame to be true

Is there a way to overload/override the behavior of the == operator to do case-insensitive comparisons?

Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062
  • Duplicate of https://stackoverflow.com/questions/3121957/how-can-i-do-a-case-insensitive-string-comparison – Chris Akridge Dec 11 '18 at 19:55
  • 8
    Even if this were possible, it really seems like the wrong solution to the problem. Established canonical behavior would be fundamentally changed, which could have all manner of unexpected side-effects and make future support *very* difficult. – David Dec 11 '18 at 19:56
  • 2
    For string comparisons, see also [this](https://stackoverflow.com/questions/631233/is-there-a-c-sharp-case-insensitive-equals-operator), [this](https://stackoverflow.com/questions/39889362/best-way-to-compare-two-strings-ignoring-case), [this](https://stackoverflow.com/questions/501906/caselessly-comparing-strings-in-c-sharp), and probably a few others. For overloading operators for built-in types see [this](https://stackoverflow.com/questions/2587608/c-sharp-string-operator-overloading) or [this](https://stackoverflow.com/questions/618149/operator-overloading-for-builtin-types) – p.s.w.g Dec 11 '18 at 19:58
  • @p.s.w.g you may not have known, but the language changes monthly. you are pointing to posts that are years old. you should see the amount of changes going from 6.0 all the way to 7 + . – Alex Gordon Dec 11 '18 at 20:00
  • 7
    @l--''''''---------'''''''''''' It doesn't change that much. Features are added, but core functionality doesn't really change. The answers to those linked questions are still quite valid. – Abion47 Dec 11 '18 at 20:01
  • 6
    @l--''''''---------'''''''''''' any change like that would be a huge breaking change. – Daniel A. White Dec 11 '18 at 20:01
  • 1
    lol it's interesting there's such harsh criticism of this question and all they could say was that it was "too broad" – Alex Gordon Dec 12 '18 at 18:30

2 Answers2

4

You can't but you can use StringComparer.OrdinalIgnoreCase.Equals(...) or use StringComparer.CurrentCultureIgnoreCase (depending on your needs).

If you really don't want to change the code in a significant way, consider wrapping the values in a value-object pattern. You could add implicit conversions to System.String but provide the operators you want.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • i dont want to have to do that throughout my code base – Alex Gordon Dec 11 '18 at 19:55
  • muich cleaner to do .ToLower() anyway – Alex Gordon Dec 11 '18 at 19:56
  • @l--''''''---------'''''''''''' sorry thats not an option. you could wrap the strings in a value object pattern and control it that way. – Daniel A. White Dec 11 '18 at 19:56
  • @l--''''''---------'''''''''''' with the `StringComparer`, its safe for `null`. – Daniel A. White Dec 11 '18 at 19:56
  • cool i didnt know that == was not safe with nulls – Alex Gordon Dec 11 '18 at 19:57
  • 1
    i mean calling `.ToLower()` is not safe with nulls. – Daniel A. White Dec 11 '18 at 19:57
  • yep i gotcha - i actually didnt know it wasnt safe with nulls, this is a problem with C#'s defintiion of that method, you would think if a method is operating on the entire set of `string` that it would be valid for `null` – Alex Gordon Dec 11 '18 at 19:58
  • 2
    @l--''''''---------'''''''''''' It's not really a problem with that method, it's a core feature of the language. Accessing any non-static member of a null object will throw a `NullReferenceException` (excluding extension methods). You could always use the null-conditional operator if you want 'safe' member access, e.g. `foo?.ToLower()`, but I would still recommend a using proper `StringComparer` or `String.Equals`. – p.s.w.g Dec 11 '18 at 20:05
  • I also vote for if(somestring.Equals(someotherstring,StringComparison.OrdinalIgnoreCase)){ – Jonathan Shields Dec 11 '18 at 20:40
3

You can't override operators for pre-existing classes. The closest you can get is to make an extension method:

public static bool EqualsCaseInsensitive(this String a, String b) {
  return String.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}

You can use it like so:

var areSame = stringA.EqualsCaseInsensitive(stringB);

That being said, it's considered bad practice to add extension methods to core types like String. You'd be better off just having a utility method do the comparison instead. And in this particular case, the utility method you need already exists:

var areSame = String.Equals(stringA, stringB, StringComparison.OrdinalIgnoreCase);
Abion47
  • 22,211
  • 4
  • 65
  • 88
  • Can you link to something that says it's bad practice to add extension methods to built-in types (or explain why)? I would like to read that. – Rufus L Dec 11 '18 at 20:21
  • @RufusL Extension methods are used pretty useful when used in moderation, but it can get ugly if you rely on them extensively. Since a `string` will likely appear in almost every code file, extending it will quickly start to feel like 'pollution'. Where you draw the line between 'just right' and 'too much' is mostly subjective though. There's been some discussion around this topic on se.so: [here](https://softwareengineering.stackexchange.com/q/329655/81884) and [here](https://softwareengineering.stackexchange.com/q/77427/81884), but it mostly boils down to taste. – p.s.w.g Dec 11 '18 at 20:41
  • @RufusL There's also the viewpoint that an overuse of extension methods leads to a prototype-oriented programming style that is hidden by object-oriented syntax. [Some people](https://daedtech.com/why-i-dont-like-c-extension-methods/) feel like this leads to not knowing what you are actually doing when coding. I'm not sure I fully agree with that perspective, but it's an interesting one to read about. – Abion47 Dec 11 '18 at 21:08
  • @p.s.w.g Oh, you're talking about quantity of methods, then. Not adding them to "core types"... – Rufus L Dec 11 '18 at 21:17
  • @RufusL More about 'what actual value does this method provide over the alternative?' Simple interfaces such as `IEnumerable` get extended a lot (see Linq) because a single method can replace a very lengthy `for each` loop and often improves code reuse. But when adding very small utility methods to a core type, it's usually not worth it -- is an extension method like `someString.Append("foo")` really any better than `someString + "foo"`? – p.s.w.g Dec 11 '18 at 21:27
  • @RufusL I didn't address your question because it seemed like p.s.w.g handled that, I just thought I'd add another perspective from an article I found on the subject. The reason it's generally considered bad practice to extend core objects is the same reason people in the Javascript world frown on extending/overriding functions in global objects - because it can easily lead to unexpected behavior if abused. If you import a library that adds an extension method with the same name but different behavior, it can be difficult to know what will actually happen, so it's best to just not go there. – Abion47 Dec 11 '18 at 23:51
  • @RufusL And also to reiterate what p.s.w.g said, for small utility methods it just isn't worth the effort. You might feel like you're making clever or convenient use of it when in reality you're just making things more complicated than they need to be. Do you really _need_ to be able to call `EqualsCaseInsensitive` directly on the string object when a utility method would fill the same purpose? And it may look like it's more readable, but you or someone else is going to come across that code later and not know if it's an extension method or a method on the object itself, and confusion ensues. – Abion47 Dec 11 '18 at 23:55
  • @RufusL Not to mention for _this_ particular example, the utility method already exists - it's the one that is wrapped by the extension method in my answer. :P – Abion47 Dec 11 '18 at 23:56
  • 1
    Thanks! So after all that, then, why did you answer this with an extension method?? The answer could just be a static method or `var areSame = "alex".Equals("ALex", StringComparison.OrdinalIgnoreCase);` :D – Rufus L Dec 12 '18 at 00:12
  • @RufusL For questions that have ill-advised solutions, the policy on SO is (usually) to answer the question as asked, and then explain why you shouldn't do it that way. In this case, you wanted to know how to get that behavior, so I told you how... and then I told you why you should just go with a utility method instead. Personally, I think that there is no grand truth and there's nothing that you should just plain never do. Everything has a purpose, and for certain things the advice is to not do it a certain way _unless you know what you're doing and have a good reason to do it that way._ – Abion47 Dec 12 '18 at 00:17
  • @RufusL Sort of like the `goto` statement in C#. It exists, but it's almost universally panned as something you should never do... except Microsoft uses it in the .NET source code quite frequently. The difference is that with their experience and expertise, they know when and how to use it correctly, but for someone who doesn't, it's very easy to fall into a trap of abusing it and end up with incredibly messy and error-prone code. Thus, for most programmers, the rule of thumb is to just not use it, then when you get more experienced, you can make an educated decision for yourself. – Abion47 Dec 12 '18 at 00:21