String.IsNullOrEmpty() Check for Space - c#

What is needed to make String.IsNullOrEmpty() count whitespace strings as empty?
Eg. I want the following to return true instead of the usual false:
String.IsNullOrEmpty(" ");
Is there a better approach than:
String.IsNullOrEmpty(" ".Trim());
(Note that the original question asked what the return would be normally hence the unsympathetic comments, this has been replaced with a more sensible question).

.NET 4.0 will introduce the method String.IsNullOrWhiteSpace. Until then you'll need to use Trim if you want to deal with white space strings the same way you deal with empty strings.
For code not using .NET 4.0, a helper method to check for null or empty or whitespace strings can be implemented like this:
public static bool IsNullOrWhiteSpace(string value)
{
if (String.IsNullOrEmpty(value))
{
return true;
}
return String.IsNullOrEmpty(value.Trim());
}
The String.IsNullOrEmpty will not perform any trimming and will just check if the string is a null reference or an empty string.

String.IsNullOrEmpty(" ")
...Returns False
String foo = null;
String.IsNullOrEmpty( foo.Trim())
...Throws an exception as foo is Null.
String.IsNullOrEmpty( foo ) || foo.Trim() == String.Empty
...Returns true
Of course, you could implement it as an extension function:
static class StringExtensions
{
public static bool IsNullOrWhiteSpace(this string value)
{
return (String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim()));
}
}

Related

Regex.IsMatch returning True which is not correct

I have an extension method like this;
public static bool IsBoolean(this string value)
{
string lower = value.ToLower(CultureInfo.InvariantCulture);
return new Regex("[true]|[false]|[0]|[1]", RegexOptions.Compiled).IsMatch(lower);
}
But this regex pattern fails when I give "fals" or "tru" as value. Such as;
[Theory(DisplayName = "IsBoolean")]
[InlineData("FALS")]
[InlineData("Fals")]
[InlineData("TRU")]
[InlineData("Tru")]
public void IsNotBoolean(string value)
{
bool result = value.IsBoolean();
Assert.False(result);
}
All these tests has been failed. Because result is true.
How is this possible? Is this regex pattern wrong ?
You want check if the string is any one of the following, ignoring case,
true
false
1
0
Then you just separate those strings with | and use that as the regex, and use the IgnoreCase option:
public static bool IsBoolean(this string value) {
// note the ^ and $. They assert the start and end of the string.
return new Regex("^(?:true|false|0|1)$", RegexOptions.IgnoreCase).IsMatch(value);
}
[] denotes a character class, so it will match any one character inside it. [abc] matches either a, b or c. Note the difference.

Overwrite the == operator globally

In a lot of places I'm using the == operator to compare the string, now I know this considers casing... Is there anyway I can adjust the culture settings to avoid this or do I have to go to every line of code and change it to
string.Compare(a,b,StringComparison.CurrentCultureIgnoreCase)
How about a string extension method?:
public static class StringExtensions {
public static bool EqualsIC(this string self, string string1) {
return self.Equals(string1, StringComparison.InvariantCultureIgnoreCase);
}
}
Then you can just use
string string1 = "Hello world";
string string2 = "hEllO WOrLD";
bool theymatch = string1.EqualsIC(string2);
// OR (per TimS' comment) - to avoid error if string1 is null
theymatch = StringExtensions.EqualsIC(string1, string2);
As an esoteric alternative, you could use Regex instead of String.Compare:
public static bool EqualsICRX(this string self, string string1) {
return Regex.IsMatch(string1, "^" + self + "$", RegexOptions.IgnoreCase);
}
== on strings never considers the culture, so you have to change it.
String == actually is done based only on codepoints, so strings can differ even when looking the same (e.g. if one has composed characters and the other decomposed). Generally you want a more complex notion of 'equality'.
"é" == "é"
== False

Check if string is empty or all spaces in C#

How to easily check if a string is blank or full of an undetermined amount of spaces, or not?
If you have .NET 4, use the string.IsNullOrWhiteSpace method:
if(string.IsNullOrWhiteSpace(myStringValue))
{
// ...
}
If you don't have .NET 4, and you can stand to trim your strings, you could trim it first, then check if it is empty.
Otherwise, you could look into implementing it yourself:
.Net 3.5 Implementation of String.IsNullOrWhitespace with Code Contracts
If it's already known to you that the string is not null, and you just want to make sure it's not a blank string use the following:
public static bool IsEmptyOrWhiteSpace(this string value) =>
value.All(char.IsWhiteSpace);
If you literally need to know if the "string is blank or full of an undetermined amount of spaces", use LINQ as #Sonia_yt suggests, but use All() to ensure that you efficiently short-circuit out as soon as you've found a non-space.
(This is give or take the same as Shimmy's, but answers the OP's question as written to only check for spaces, not any and all whitespace -- \t, \n, \r, etc.)
/// <summary>
/// Ensure that the string is either the empty string `""` or contains
/// *ONLY SPACES* without any other character OR whitespace type.
/// </summary>
/// <param name="str">The string to check.</param>
/// <returns>`true` if string is empty or only made up of spaces. Otherwise `false`.</returns>
public static bool IsEmptyOrAllSpaces(this string str)
{
return null != str && str.All(c => c.Equals(' '));
}
And to test it in a console app...
Console.WriteLine(" ".IsEmptyOrAllSpaces()); // true
Console.WriteLine("".IsEmptyOrAllSpaces()); // true
Console.WriteLine(" BOO ".IsEmptyOrAllSpaces()); // false
string testMe = null;
Console.WriteLine(testMe.IsEmptyOrAllSpaces()); // false
private bool IsNullOrEmptyOrAllSpaces(string str)
{
if(str == null || str.Length == 0)
{
return true;
}
for (int i = 0; i < str.Length; i++)
{
if (!Char.IsWhiteSpace(str[i])) return false;
}
return true;
}
Try use LinQ to solve?
if(from c in yourString where c != ' ' select c).Count() != 0)
This will return true if the string is not all spaces.

?? operator in system.DBNull

Is there an operator or built in function to simplyfy this:
myVal = object1.object2.something(a,b).dataColumn.toString()==""?object1.object2.something(a,b).dataColumn.toString():"-";
I know i can do something like:
string str = object1.object2.something(a,b).dataColumn.toString();
myVal =str==""?"-":str;
but I have many objects and I want to avoid it:
string str1 = object1.object2.something(a,b).dataColumn1.toString();
myVal1==""?str1:"-"
string str2 = object1.object2.something(a,b).dataColumn2.toString();
myVal2==""?str2:"-"
:
string strN = object1.object2.something(a,b).dataColumnN.toString();
myValN==""?strN:"-"
I can also create a function:
private string CheckNull(object dataColumn){
return dataColumn == System.DBNull?"-":dataColumn.toString();
}
myVal1 = CheckNull(object1.object2.something1(a,b).dataColumn.toString())
myVal2 = CheckNull(object1.object2.something2(a,b).dataColumn.toString())
myVal3 = CheckNull(object1.object2.something3(a,b).dataColumn.toString())
The easiest way is to use the ?? operator but the problem is that 'dataColumn' is not compatible with ?? because sometimes returns a system.DBNull instead of a null. Look at the immediate window output:
System.DBNull??"-"
'System.DBNull' is a 'type', which is not valid in the given context
null??"-"
"-"
I wonder if there is some (string) function or operator that can return "-" if dataColumn.toString()=="" without an if..then (because I would have to make many if..then for all of them. Otherwise I rather use the function approach shown above.
string str = object1.object2.something(a,b).dataColumn.toString().if("","-");
How about:
public static class StringHelper {
public static string ValueOrDash(this string value) {
return string.IsNullOrEmpty(value) ? "-" : value;
}
}
Then you can just do:
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrDash();
Or better yet:
public static class StringHelper {
public static string ValueOrWhatever(this string value, string defaultValue) {
return string.IsNullOrEmpty(value) ? defaultValue : value;
}
}
myVal = object1.object2.something(a,b).DataColumn.ToString().ValueOrWhatever("-");
If the underlying object is always either a string or DbNull, you could use the as cast operator:
private string CheckNull(object dataColumn){
return dataColumn == (dataColumn as string)??"-":dataColumn;
}
This will also return "-" if the value is an integer for example or some other type.
It's not clear from your code, but if these values are coming from DataRows you could use the new (.NET 3.5) DataRowExtensions.Field function, which will return null instead of DbNull.
You could write an extension method to call on the dataColumn. It wouldn't functionally be much different than your CheckNull method, though.
Or in your first example with str1, str2, strN and such, is there a reason you can't reuse str1 for each? I see you have a method call in your long line of code, you wouldn't want to waste the time running that more often than you need to (especially if it's going to result in the same output every time).

BestPractice - Transform first character of a string into lower case

I'd like to have a method that transforms the first character of a string into lower case.
My approaches:
1.
public static string ReplaceFirstCharacterToLowerVariant(string name)
{
return String.Format("{0}{1}", name.First().ToString().ToLowerInvariant(), name.Substring(1));
}
2.
public static IEnumerable<char> FirstLetterToLowerCase(string value)
{
var firstChar = (byte)value.First();
return string.Format("{0}{1}", (char)(firstChar + 32), value.Substring(1));
}
What would be your approach?
I would use simple concatenation:
Char.ToLowerInvariant(name[0]) + name.Substring(1)
The first solution is not optimized because string.Format is slow and you don't need it if you have a format that will never change. It also generates an extra string to covert the letter to lowercase, which is not needed.
The approach with "+ 32" is ugly / not maintainable as it requires knowledge of ASCII character value offsets. It will also generate incorrect output with Unicode data and ASCII symbol characters.
Depending on the situation, a little defensive programming might be desirable:
public static string FirstCharacterToLower(string str)
{
if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
return str;
return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}
The if statement also prevents a new string from being built if it's not going to be changed anyway. You might want to have the method fail on null input instead, and throw an ArgumentNullException.
As people have mentioned, using String.Format for this is overkill.
Just in case it helps anybody who happens to stumble across this answer.
I think this would be best as an extension method, then you can call it with yourString.FirstCharacterToLower();
public static class StringExtensions
{
public static string FirstCharacterToLower(this string str)
{
if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
{
return str;
}
return Char.ToLowerInvariant(str[0]) + str.Substring(1);
}
}
The fastest solution I know without abusing c#:
public static string LowerCaseFirstLetter(string value)
{
if (value?.Length > 0)
{
var letters = value.ToCharArray();
letters[0] = char.ToLowerInvariant(letters[0]);
return new string(letters);
}
return value;
}
Mine is
if (!string.IsNullOrEmpty (val) && val.Length > 0)
{
return val[0].ToString().ToLowerInvariant() + val.Remove (0,1);
}
I like the accepted answer, but beside checking string.IsNullOrEmpty I would also check if Char.IsLower(name[1]) in case you are dealing with abbreviation. E.g. you would not want "AIDS" to become "aIDS".
If you care about performance I would go with
public static string FirstCharToLower(this string str)
=> string.Create(str.Length, str, (output, input) =>
{
input.CopyTo(output);
output[0] = char.ToLowerInvariant(input[0]);
});
I did some quick benchmarking and it seems to be at least twice as fast as the fastest solution posted here and 3.5 times faster than the worst one across multiple input lengths.
There is no input checking as it should be the responsibility of the caller. Allowing you to prepare your data in advance and do fast bulk processing not being slowed down by having branches in your hot path if you ever need it.
With range operator C# 8.0 or above you can do this:
Char.ToLowerInvariant(name[0]) + name[1..];
Combined a few and made it a chainable extension. Added short-circuit on whitespace and non-letter.
public static string FirstLower(this string input) =>
(!string.IsNullOrWhiteSpace(input) && input.Length > 0
&& char.IsLetter(input[0]) && !char.IsLower(input[0]))
? input[0].ToString().ToLowerInvariant() + input.Remove(0, 1) : input;
This is a little extension method using latest syntax and correct validations
public static class StringExtensions
{
public static string FirstCharToLower(this string input)
{
switch (input)
{
case null: throw new ArgumentNullException(nameof(input));
case "": throw new ArgumentException($"{nameof(input)} cannot be empty", nameof(input));
default: return input.First().ToString().ToLower() + input.Substring(1);
}
}
}
Use This:
string newName= name[0].ToString().ToLower() + name.Substring(1);
If you don't want to reference your string twice in your expression you could do this using System.Linq.
new string("Hello World".Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())
That way if your string comes from a function, you don't have to store the result of that function.
new string(Console.ReadLine().Select((c, i) => i == 0 ? char.ToLower(c) : c).ToArray())
It is better to use String.Concat than String.Format if you know that format is not change data, and just concatenation is desired.

Categories