Is there a C# case insensitive equals operator? - c#

I know that the following is case sensitive:
if (StringA == StringB) {
So is there an operator which will compare two strings in an insensitive manner?

Try this:
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

The best way to compare 2 strings ignoring the case of the letters is to use the String.Equals static method specifying an ordinal ignore case string comparison. This is also the fastest way, much faster than converting the strings to lower or upper case and comparing them after that.
I tested the performance of both approaches and the ordinal ignore case string comparison was more than 9 times faster! It is also more reliable than converting strings to lower or upper case (check out the Turkish i problem). So always use the String.Equals method to compare strings for equality:
String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);
If you want to perform a culture specific string comparison you can use the following code:
String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);
Please note that the second example uses the the string comparison logic of the current culture, which makes it slower than the "ordinal ignore case" comparison in the first example, so if you don't need any culture specific string comparison logic and you are after maximum performance, use the "ordinal ignore case" comparison.
For more information, read the full story on my blog.

There are a number of properties on the StringComparer static class that return comparers for any type of case-sensitivity you might want:
StringComparer Properties
For instance, you can call
StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)
or
StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)
It's a bit cleaner than the string.Equals or string.Compare overloads that take a StringComparison argument.

System.Collections.CaseInsensitiveComparer
or
System.StringComparer.OrdinalIgnoreCase

string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);

or
if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {
but you need to be sure that StringA is not null. So probably better tu use:
string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);
as John suggested
EDIT: corrected the bug

You can use
if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))

Operator? NO, but I think you can change your culture so that string comparison is not case-sensitive.
// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo
I'm confident that it will change the way that strings are being compared by the equals operator.

Here an idea to simplify the syntax:
public class IgnoreCase
{
private readonly string _value;
public IgnoreCase(string s)
{
_value = s;
}
protected bool Equals(IgnoreCase other)
{
return this == other;
}
public override bool Equals(object obj)
{
return obj != null &&
(ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
}
public override int GetHashCode()
{
return _value?.GetHashCode() ?? 0;
}
public static bool operator ==(IgnoreCase a, IgnoreCase b)
{
return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
}
public static bool operator !=(IgnoreCase a, IgnoreCase b)
{
return !(a == b);
}
public static implicit operator string(IgnoreCase s)
{
return s._value;
}
public static implicit operator IgnoreCase(string s)
{
return new IgnoreCase(s);
}
}
Usable like:
Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

I am so used to typing at the end of these comparison methods: , StringComparison.
So I made an extension.
namespace System
{ public static class StringExtension
{
public static bool Equals(this string thisString, string compareString,
StringComparison stringComparison)
{
return string.Equals(thisString, compareString, stringComparison);
}
}
}
Just note that you will need to check for null on thisString prior to calling the ext.

string.Compare(string1, string2, true)

Others answer are totally valid here, but somehow it takes some time to type StringComparison.OrdinalIgnoreCase and also using String.Compare.
I've coded simple String extension method, where you could specify if comparison is case sensitive or case senseless with boolean - see following answer:
https://stackoverflow.com/a/49208128/2338477

if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {
People report ToUpperInvariant() is faster than ToLowerInvariant().

//You can make it case insensitive by
s1.ToLower() == s2.ToLower();

Related

How to simplify this C# if/else syntax

I have the following statement:
serverCard.Details = !String.IsNullOrEmpty(card.Details) ? card.Details : serverCard.Details;
I want to check and see if card.Details is null or empty... if not, write the value. Is there any syntax that allows me to leave out the else conditional?
Sure, just use a regular if:
if(!String.IsNullOrEmpty(card.Details))
serverCard.Details = card.Details
You can always use the old if statement:
if(!String.IsNullOrEmpty(card.Details))
{
serverCard.Details = card.Details;
}
I think the ternary operator is not needed here.
You can write an extension method for String to check if nullOrEmpty. The regular if then would be shorter
Extension Method:
public static bool IsNullOrEmpty(this string str)
{
return string.IsNullOrEmpty(str);
}
public static bool IsNullOrWhiteSpace(this string str)
{
return string.IsNullOrWhiteSpace(str);
}
The if:
if(!card.Details.IsNullOrWhiteSpace())
serverCard.Details = card.Details
The extension method will work for every string.

string to bool inline conversion

What I currently have:
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
Convert.ToBoolean(Ctx.Request["okPress"]);
Correct me if I'm wrong here, but wouldn't this throw a FormatException if the string isn't "true/True" or "false/False"? Is there any way to handle the conversion in one row, without having to worry about exceptions? Or do I need to use Boolean.TryParse?
You can use Boolean.TryParse:
bool okPress;
bool success = Boolean.TryParse(Ctx.Request["okPress"]), out okPress);
For what it's worth, here a "one-liner", create following extension which might be useful especially in LINQ queries:
public static bool TryGetBool(this string item)
{
bool b;
Boolean.TryParse(item, out b);
return b;
}
and write:
bool okPress = Ctx.Request["okPress"].TryGetBool();
IF you didn't want to use TryParse You could do something like
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
(Ctx.Request["okPress"].ToLower()=="true");
This way if the string is not true/false it will just assume false for you with no exceptions thrown.
This does of course assume that you are happy for a value of "fish" to be treated as false rather than as an exception.
Better though is to just not do it as a single line. You don't generally have a maximum number of lines of code so two or three simple lines of code are often better than one complicated line of code...
Why don't you compare the string against true?
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
String.Compare(Ctx.Request["okPress"], "true", StringComparison.OrdinalIgnoreCase) == 0
You can use TryParse method of Boolean class as you said.
Tries to convert the specified string representation of a logical
value to its Boolean equivalent. A return value indicates whether the
conversion succeeded or failed.
bool result = Boolean.TryParse(Ctx.Request["okPress"]), out okPress);
It returns true if value was converted successfully; otherwise, false.
Your inline conversion.
public static bool TryParseAsBoolean(this string expression)
{
bool booleanValue;
bool.TryParse(expression, out booleanValue);
return booleanValue;
}
bool okPress = Ctx.Request["okPress"].TryParseAsBoolean();

How can I do a case insensitive string comparison?

How can I make the line below case insensitive?
drUser["Enrolled"] =
(enrolledUsers.FindIndex(x => x.Username == (string)drUser["Username"]) != -1);
I was given some advice earlier today that suggested I use:
x.Username.Equals((string)drUser["Username"], StringComparison.OrdinalIgnoreCase)));
the trouble is I can't get this to work, I've tried the line below, this compiles but returns the wrong results, it returns enrolled users as unenrolled and unenrolled users as enrolled.
drUser["Enrolled"] =
(enrolledUsers.FindIndex(x => x.Username.Equals((string)drUser["Username"],
StringComparison.OrdinalIgnoreCase)));
Can anyone point out the problem?
This is not the best practice in .NET framework (4 & +) to check equality
String.Compare(x.Username, (string)drUser["Username"],
StringComparison.OrdinalIgnoreCase) == 0
Use the following instead
String.Equals(x.Username, (string)drUser["Username"],
StringComparison.OrdinalIgnoreCase)
MSDN recommends:
Use an overload of the String.Equals method to test whether two strings are equal.
Use the String.Compare and String.CompareTo methods to sort strings, not to check for equality.
Please use this for comparison:
string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
You should use static String.Compare function like following
x => String.Compare (x.Username, (string)drUser["Username"],
StringComparison.OrdinalIgnoreCase) == 0
Others answer are totally valid here, but somehow it takes some time to type StringComparison.OrdinalIgnoreCase and also using String.Compare.
I've coded simple String extension method, where you could specify if comparison is case sensitive or case senseless with boolean, attaching whole code snippet here:
using System;
/// <summary>
/// String helpers.
/// </summary>
public static class StringExtensions
{
/// <summary>
/// Compares two strings, set ignoreCase to true to ignore case comparison ('A' == 'a')
/// </summary>
public static bool CompareTo(this string strA, string strB, bool ignoreCase)
{
return String.Compare(strA, strB, ignoreCase) == 0;
}
}
After that whole comparison shortens by 10 characters approximately - compare:
Before using String extension:
String.Compare(testFilename, testToStart,true) != 0
After using String extension:
testFilename.CompareTo(testToStart, true)
You can (although controverse) extend System.String to provide a case insensitive comparison extension method:
public static bool CIEquals(this String a, String b) {
return a.Equals(b, StringComparison.CurrentCultureIgnoreCase);
}
and use as such:
x.Username.CIEquals((string)drUser["Username"]);
C# allows you to create extension methods that can serve as syntax suggar in your project, quite useful I'd say.
It's not the answer and I know this question is old and solved, I just wanted to add these bits.
I'd like to write an extension method for EqualsIgnoreCase
public static class StringExtensions
{
public static bool? EqualsIgnoreCase(this string strA, string strB)
{
return strA?.Equals(strB, StringComparison.CurrentCultureIgnoreCase);
}
}
I think you will find more information in this link:
http://codeidol.com/community/dotnet/controlling-case-sensitivity-when-comparing-two-st/8873/
Use the Compare static method on the String class to compare the two strings. Whether the comparison is case-insensitive is determined by the third parameter of one of its overloads. For example:
string lowerCase = "abc";
string upperCase = "AbC";
int caseInsensitiveResult = string.Compare(lowerCase, upperCase,
StringComparison.CurrentCultureIgnoreCase);
int caseSensitiveResult = string.Compare(lowerCase,
StringComparison.CurrentCulture);
The caseSensitiveResult value is -1 (indicating that lowerCase is "less than" upperCase) and the caseInsensitiveResult is zero (indicating that lowerCase "equals" upperCase).
How about using StringComparison.CurrentCultureIgnoreCase instead?
you can always use functions:
.ToLower();
.ToUpper();
convert your strings and then compare them...
Good Luck

Null and blank values

What's the best way of writing robust code so that a variable can be checked for null and blank.
e.g.
string a;
if((a != null) && (a.Length() > 0))
{
//do some thing with a
}
For strings, there is
if (String.IsNullOrEmpty(a))
You can define an extension method to allow you to do this on many things:
static public bool IsNullOrEmpty<T>(this IEnumerable <T>input)
{
return input == null || input.Count() == 0;
}
It already exists as a static method on the System.String class for strings, as has been pointed out.
And if you are using .NET 4.0 you might want to take a look at String.IsNullOrWhiteSpace.
From version 2.0 you can use IsNullOrEmpty.
string a;
...
if (string.IsNullOrEmpty(a)) ...
if(string.IsNullOrEmpty(string name))
{
/// write ur code
}
for strings:
string a;
if(!String.IsNullOrEmpty(a))
{
//do something with a
}
for specific types you could create an extention method
note that i've used HasValue instead of IsNullorEmpty because 99% of the times you will have to use the !-operator if you use IsNullOrEmpty which I find quite unreadable
public static bool HasValue(this MyType value)
{
//do some testing to see if your specific type is considered filled
}
I find Apache Commons.Lang StringUtils (Java)'s naming a lot easier: isEmpty() checks for null or empty string, isBlank() checks for null, empty string, or whitespace-only. isNullOrEmpty might be more descriptive, but empty and null is, in most cases you use it, the same thing.

String comparison equivalents

I believe these 2 lines are equivalent but after running into a strange issue I no longer believe this to be the case.
String mimeType = context.Request.ContentType;
(String.Compare("text/xml", mimeType, true) == 0))
is the same as :
context.Request.ContentType.ToLower().Equals("text/xml")
Are their implementations in the CLR any different?
They are not equivalent, and ToLower/ToUpper may have some localization issues. The way to compare two strings without case-sensitivity (considering one of the strings may be null, which is why I don't like the str1.Equals method) is the static String.Equals method:
bool areEqual = String.Equals(str1, str2, StringComparison.OrdinalIgnoreCase);
They are not completely equivalent; see here.
Here is the correct way to do a case insensitive comparison:
bool areSame = str1.Equals(str2, StringComparison.OrdinalIgnoreCase);
This way will also be more efficient becasue it doesn't allocate a separate string for the lowercase copy.
In addition to the other answers (#SLaks, #Serhio), I also feel obligated to point out that .ToLower() generates another string. Compare does not as far as I know. Excessive string generation in an app can come back to bite you in terms of memory usage and performance if it is in frequently called code.
the implementation of Compare(string, string, boolean) in .NET:
public static int Compare(string strA, string strB, bool ignoreCase)
{
if (ignoreCase)
{
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
}
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
}
and Equals
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public bool Equals(string value)
{
if ((value == null) && (this != null))
{
return false;
}
return EqualsHelper(this, value);
}
So, is NOT the same thing.

Categories

Resources