I'm new to C# I came from a Java background, I'm trying to find a method to compare 2 strings if they are equal but to the ignore case.
In Java you can type somthing like this
boolean equal = "abc".equalsIgnoreCase("ABC");
is there anything like that in C# ?. I know that I can use
var equal = String.Compare("abc", "ABC", StringComparison.OrdinalIgnoreCase);
or
var equal = String.Equals("abc", "ABC", StringComparison.InvariantCultureIgnoreCase);
I just want to know if there is anything shorter (without having to pass a StringComparison Enum )
you can create an extension method:
internal static class StringExtensions
{
public static bool EqualsIgnoreCase(this string str1, string str2)
{
return String.Equals(str1, str2, StringComparison.InvariantCultureIgnoreCase);
}
}
Then use it this way: bool equals = "abc".EqualsIgnoreCase("ABC");
Related
Why is this passing Assert.AreSame()?
[TestMethod]
public void StringSameTest()
{
string a = "Hello";
string b = "Hello";
Assert.AreSame(a, b);
}
I understand ìt tests for reference equality, and is essentially the same as Assert.IsTrue(object.ReferenceEquals(a, b)) but it's clear that a and b are different string objects, regardless of them having the same values. If Ì set string b = a; I'd expect true, but that's not the case. Why isn't this test failing?
Thanks
The C# compiler will intern identical literal strings to the same const string reference.
So your code is equivalent to this:
private const String _hello = "Hello";
[TestMethod]
public void StringSameTest()
{
string a = _hello;
string b = _hello;
Assert.AreSame( a, b ); // true
}
To create a separate string instance that's identical to a const string use String.Copy():
string a = "Hello";
string b = a.Copy();
Assert.AreSame( a, b ); // false
However, do note that:
String.Copy() and String.Clone() are different!
Clone() does not actually clone the string value, it instead returns a reference to itself.
String.ToString() also returns a reference to itself.
String.Copy() is deprecated in .NET Framework and .NET Core and may be removed in a future version.
This is because there is no legitimate need to use String.Copy()
See Do string literals get optimised by the compiler?
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.
here is C# code.
class Program
{
static void Main(string[] args)
{
char [] arry = {'a', 'b', 'c'};
String str1 = 'a' + "bc";
String str2 = "bcd";
String str3 = new String(arry);
if (str1 == str2)
Console.WriteLine("str1 == str2");
if (str1 == str3)
Console.WriteLine("str1 == str3");
if (String.Equals(str1, str3))
Console.WriteLine("String.Equals(str1, str3)");
String str4 = GetStr();
if (str1 == str4)
Console.WriteLine("str1 == str4");
if (String.Equals(str1, str4))
Console.WriteLine("String.Equals(str1, str4)");
if (str3 == str4)
Console.WriteLine("str3 == str4");
if (String.Equals(str3, str4))
Console.WriteLine("String.Equals(str3, str4)");
}
public static String GetStr()
{
String str = "ab" + 'c';
return str;
}
}
And result is ..
str1 == str3
String.Equals(str1, str3)
str1 == str4
String.Equals(str1, str4)
str3 == str4
String.Equals(str3, str4)
Why all results say "Equal!" ??
As I knew, reference value are different each others.
So, results should have been "different!". but not.
Why?
It seems that there is no reason to use String.equal() !!
You are confusing string.Equals with object.ReferenceEquals.
string.Equals overrides object.Equals (which has the same semantics as ReferenceEquals) and works by comparing the values of the strings. This is the reason that object.Equals is virtual in the first place.
Equality for a string has been overridden to be based on its value.
The documentation for String.Equals states it checks the value, but that also happens to be what == also does due to the string implementation.
Default equality for reference types is based on the reference itself, but that can easily be overridden... so basically your assertion is flawed, as it doesn't take into account types that override default behaviour.
As Jon has stated, reference equality can be forced via the object.ReferenceEquals static method, but as Jason has stated, this may also fail if the strings have been interned.
According to ILSpy, String.Equals ends up using == at any rate:
public static bool Equals(string a, string b)
{
return a == b || (a != null && b != null && a.Length == b.Length && string.EqualsHelper(a, b));
}
== has been overloaded for String to evaluate equality as values, not as references. From MSDN:
Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references.
However, what you need to be aware of is that some of the strings will be evaluated at compile-time, and the compiler will intern them (that is, hold a single reference to a string with a given value). Therefore, these strings might be equal as references too (but that is not guaranteed to be the case).
String.Equals Method
Determines whether two String objects have the same value.
This means that your ouput is completely normal.
Each string literal does not necessarily result in a new string instance. When two or more string literals that are equivalent according to the string equality operator appear in the same assembly, these string literals refer to the same string instance. For instance, the output produced by
class Test
{
static void Main() {
object a = "hello";
object b = "hello";
System.Console.WriteLine(a == b);
}
}
is True because the two literals refer to the same string instance.
you can see this for completely:
http://msdn.microsoft.com/en-us/library/aa691090%28v=vs.71%29.aspx
For comparing string you should use:
var1string.CompareTo(var2string) == 0
This is the correct way to compare strings
So change :
if (str1 == str2)
with this:
if (str1.CompareTo(str2) == 0)
And the rest too.
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();
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();