.Trim() when string is empty or null - c#

I'm receiving some data from the client in the form of json.
I'm writing this:
string TheText; // or whould it be better string TheText = ""; ?
TheText = ((serializer.ConvertToType<string>(dictionary["TheText"])).Trim());
If the variable that's being parsed from json comes back empty, does this code crash when I call the .Trim() method?
Thanks.

You can use elvis operator, also known as "null-conditional-operators":
GetNullableString()?.Trim(); // returns NULL or trimmed string
More info: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators

If the serializer returns an empty string, Trim will do nothing.
If the serializer returns null, you will get a NullReferenceException on the call to Trim.
Your code would be better written (as far as initialization is concerned) like this:
string theText =
((serializer.ConvertToType<string>(dictionary["TheText"])).Trim());
There is no point in declaring and initializing the variable and the immediately assigning to it.
The following would be safest, if you don't know what the serializer might return:
string theText = ((serializer.ConvertToType<string>(dictionary["TheText"])));
if(!string.IsNullOrEmpty(theText))
{
theText = theText.Trim();
}

Calling Trim() on an empty string will result in an empty string. Calling Trim() on null will throw NullReferenceException

If you have a few fields you wish to trim but your getting exceptions for those records that have nulls in certain fields, then writing a quick extension method will be the easiest method:
public static class ExtensionMethods
{
public static string TrimIfNotNull(this string value)
{
if (value != null)
{
return value.Trim();
}
return null;
}
}
Sample example of use:
string concatenated = String.Format("{0} {1} {2}", myObject.fieldOne.TrimIfNotNull(), myObject.fieldTwo.TrimIfNotNull(), myObject.fieldThree.TrimIfNotNull());

Some basic techniques to check strings against null before you trim:
(mystring ?? "").Trim()
The "null coalescing operator" ?? will return the first operand. Only when this operand is null, the second operand will be returned (as a kind of default value).
The above example will return an empty string if mystring is null.
mystring?.Trim()
The "null conditional operator" ? will short cirtuit a chain of operations in dot-notation. If the operand is null, the following operations will not be executed and null will be returned.
The above example will return null if mystring is null.
if( string.IsNullOrWhiteSpace(mystring) ) { ... }
the IsNullOrWhiteSpace() method may replace trimming if you actually want to check if there is real content in mystring. It returns true if the operand is null, empty, or nothing but whitespace characters.

As suggested in some of the comments, you may now use c# 6 Null-conditional operators with this syntax:
string TheText = (serializer.ConvertToType<string>(dictionary["TheText"]))?.Trim();
Documentation: https://msdn.microsoft.com/en-us/library/dn986595.aspx

No, it would not be better to initialize TheText to "". You're assigning to it right afterwards.
No, it won't crash – Trim() works just fine on an empty string. If by "empty" you mean that it can be null, then yes, it will crash; you could have null remain null with a null-conditional call:
string TheText =
serializer.ConvertToType<string>(dictionary["TheText"])?.Trim();

You can use the null-safe operator trim of org.apache.commons.lang
StringUtils.trim(stringOrNull)

You can use this code as beblow
string theText = (((serializer.ConvertToType<string>(dictionary["TheText"])))+ string.Empty).Trim();

Recently I had to check a string if it is null, empty or whitespace using just one if condition and for that I found out that you can add "" to a null string to make it non null.
string test = GetStringFromSomeWhere(); // null
if(string.IsNullOrEmpty(test.Trim())) { return true; } // Exception
So I did this instead
string test = GetStringFromSomeWhere() + ""; // ""
if(string.IsNullOrEmpty(test.Trim())) { return true; } // true

Related

Why does a null value automatically get converted into empty string when using string.Join?

I have a JArray that contains null values. And while I'm doing string.Join, null values are getting converted into empty string.
Original array values:
[
null,
null,
"America/Boise",
false,
"2021-02-04T06:51:33.9686227Z"
]
String.Join:
var val = $"('{string.Join("','", valuesArray)}')";
Current Result:
"('','','America/Boise','False','2/4/2021 6:51:33 AM')"
Expected Result:
"(null,null,'America/Boise',False,'2/4/2021 6:51:33 AM')"
Producing Example:
https://dotnetfiddle.net/5nRTyL
How do I get the expected result using string.Join?
null values in a JArray are stored as JTokens with a JTokenType of Null. So you'll need to check for this and convert them to the string "null". Secondly, since you only want to quote some of the values, you should not put the quotes in the separator value when you join them, but instead only quote the values that need it based on their types.
Define the following helper function:
string TokenToString(JToken token)
{
switch (token.Type)
{
case JTokenType.Null:
return "null";
case JTokenType.Date:
case JTokenType.String:
return $"'{token}'";
default:
return token.ToString();
}
}
Then you can get the result you want like this:
string val = $"({string.Join(",", valuesArray.Select(v => TokenToString(v)))})";
Working demo here: https://dotnetfiddle.net/Q62Uck
Because that's how it was designed. See the documentation for String.Join:
If separator is null, an empty string (String.Empty) is used instead. If any element in value is null, an empty string is used instead.
just replace "''" to "null".
var val = $"('{string.Join("','", valuesArray)}')".Replace("''", "null");

How to output to console a bool?

I want a concise way to output a bool? in c#. Currently, I am doing this which is very bulky.
string outputString = boolValNullable.HasValue && boolValNullable.Value ? "true" : "false";
I want to do something like:
string outputString = boolValNullable ?? "null"
The above is invalid syntax.
string output = boolValNullable?.ToString() ?? "null"
This should do the trick for you. Pass in your bool to this method and it will output to your console.
public void OutputBoolToConsole(bool? myBool)
{
var myBoolAsString = myBool?.ToString() ?? "bool is null";
Console.WriteLine(myBoolAsString);
}
Actually, you can use a conditional operator ?: for that
string outputString = boolValNullable.HasValue ? boolValNullable.Value.ToString() : "null";
or simply use Nullable<T>.ToString() method, if you want to get an empty string in case of boolValNullable equals null
string outputString = boolValNullable.ToString();
It returns
The text representation of the value of the current Nullable<T> object
if the HasValue property is true, or an empty string ("") if the
HasValue property is false.
Boolean.ToString method returns either True of False (the first letter is capital). If you need a lower case, you should add ToLower() call after ToString()

Difference between "" (Empty String) and isNot Nothing?

I am working on a condition where I have to validate whether the argument is empty or not. Lets assume that argument is Email. I have to check whether the inwards argument Email is empty or not. I can do it in several way but I am not sure which one to proceed with.
I am thinking to check from following statement:
1.Email = "" to check if email is empty string or not.
2. Email isNot Nothing
I wanna know the difference of these two functionality. If there are more function or argument related to validating empty string, You can write that too.
Thanks.
String is a reference type, which means it can have a null reference
Eg
string myString = null;
It can also be empty, which is to say, there is a reference to it, and it has 0 character length
Eg
string myString = "";
// or
string myString = string.Empty;
And just for completeness, it can also have white space
Eg
string myString = " ";
You can check for null like so
if(myString == null)
You can check for empty
if(myString == "")
// or
if(myString == string.Empty)
You can check for both, not null and not empty
if(myString != null && myString != string.Empty)
You could use Null conditional Operator with Length to check both is not null and not empty
if(myString?.Length > 0)
Or you can use the built in string methods, to make it a little easier
String.IsNullOrEmpty(String) Method
Indicates whether the specified string is null or an empty string
("").
if(string.IsNullOrEmpty(myString))
String.IsNullOrWhiteSpace(String) Method
Indicates whether a specified string is null, empty, or consists only
of white-space characters.
if(string.IsNullOrWhiteSpace(myString))
Note : It's worth noting, that IsNullOrWhiteSpace generally more robust when checking user input
Actually in C# string.Empty is equivalent to "". See String.Empty
Best way to check for Empty or Null strings is:
string.IsNullOrEmpty(Email) or you can use string.IsNullOrWhiteSpace(Email) to additionally check for white spaces.
if(!string.IsNullOrEmpty(Email))
{
// Good to proceed....
}
You should not use IsNot nothing with reference type variable. Instead, Use string.IsNullOrEmpty(Email) together with String.IsNullOrWhiteSpace(Email) while you need to validate email.

How to parse a Ternary Statement in C#

I'm accepting an input string that I want to be a ternary statement that works on strings. So my method signature would look like this:
public string Parse(string value, string ternaryStatement)
and there parameters would give these results:
Parse(null, "=?It's Null:It's Not Null") == "It's Null" // Empty string would
Parse("", "=?It's Null:It's Not Null") == "It's Null" // be same as null
This example is fairly simple, Split the string first by '?' then by ':'
But of course I need a method to handle escape characters, "\", "\?" and ":", where "\" is valid anywhere, "\?" would only be valid before the first unescaped "?" and ":" would only be valid after that same "?".
Parse(#"\?\", #"=\\\?\\?\:Match\::\:No Match\:") == ":Match:"
Parse(#"\?\", #"!=\\\?\\?\:No Match\::\:Match\:") == ":Match:"
But this is really complicated. I believe I can perform it using regular expressions, but that just creates another problem since this is well beyond my limited understanding of regular expressions. What's the best way to tackle this problem?
Edit 1
Some of the background: I'm storing a format for a URL in a database config table (It's actually Dynamics 365 for Customer Engagement, but that doesn't matter at this point). The format is stored as strings, and the parameters that are required are defined in code. So generally it looks like this:
Format: "https://something.com?Foo={0}&Bar={1}"
Description: "0 - Foo, 1 - Bar"
where the description is used both for the person that is formatting the url, and the developer that needs to know how to structure the format statement.
The problem I'm running into right now is that I have a url that requires at least one of two different parameters. If one of the values is null or empty, it will error if included in the url. So I need a way of saying, if Foo is null or Bar is null, don't include the name or &. Ideally I'd like to implement this like this:
"https://something.com?{0:=?:Foo={{0}}}&}{1:=?:Bar={{1}}}}"
So if Foo is null and Bar is "Bar" the output would be
"https://something.com?Bar=Bar"
I could also see this being used if we need to switch between a 0/1 for a boolean to true/false without having to change code:
"https://something.com?{0:=0?false:true}"
The two regexes should be:
Regex rx = new Regex(#"(?<=(?:^|[^\\])(?:\\\\)*)\?");
Regex rx2 = new Regex(#"(?<=(?:^|[^\\])(?:\\\\)*):");
Use them like:
var m = rx.Match(str);
if (m.Success)
{
int ix = m.Index;
}
The main point of the two rx is that the searched string (\? or :) must be preceded by
(?<=(?:^|[^\\])(?:\\\\)*)
that is the beginning of the string ^ or not a \ ([^\\]) plus zero or an even number of \\ that is (?:\\\\)*.
A all-in-one regex is:
Regex rx = new Regex(#"^(?<operator>=|!=|<=|>=|<|>)(?<cmp>(?:(?:\\.)|[^?:])*)\?(?<true>(?:(?:\\.)|[^?:])*):(?<false>(?:(?:\\.)|[^?:])*)$");
if (m.Success)
{
string op = m.Groups["operator"].Value;
string cmp = m.Groups["cmp"].Value;
string true1 = m.Groups["true"].Value;
string false1 = m.Groups["false"].Value;
}
In op you'll get the comparison operator used, in cmp the comparand, in true1 and false1 the true and false strings. If !m.Success then the string isn't correctly formatted. Comprehending the regex is left as a simple exercise for the reader (unless you comprehend a regex, you shouldn't ever use it, because before or later you'll have to modify it/fix it/debug it)
Solution to returning different values based on input string
Why do you need to pass in a ternary statement / wouldn't this make more sense?
string Parse(string value, string returnIfNull, string returnIfNotNull)
{
return string.IsNullOrEmpty(value) ? returnIfNull: returnIfNotNull;
}
Console.WriteLine(Parse("", "treat as null", "not expected"));
Console.WriteLine(Parse("hello", "not expected", "this value's not null"));
Parsing a ternary string for values
However, if you really need to do this, you could use something like the below:
private static readonly Regex TernaryParserRegex = new Regex(
#"^=\?(?<ifNull>(?:\\(\\\\)*:|[^:])*)(?<!\\):(?<ifNotNull>(?:\\(\\\\)*:|[^:])*)$"
/* , RegexOptions.Compiled //include this line for performance if appropriate */
);
private string[] ParseTernaryString (string ternaryStatement)
{
var results = TernaryParserRegex.Match(ternaryStatement);
if (results.Success)
{
string[] returnVal = {
results.Groups["ifNull"].Value
,
results.Groups["ifNotNull"].Value
};
return returnVal;
}
else
{
throw new Exception("Invalid Ternary Statement"); //use an appropriate exception type here; or have the function return `{null,null}` / some other default as appropriate
}
}
public string Parse(string value, string ternaryStatement)
{
var returnValues = ParseTernaryString(ternaryStatement);
return string.IsNullOrEmpty(value) ? returnValues[0]: returnValues[1];
}
//Example Usage:
Console.WriteLine(Parse("", "=?treat as null:not expected"));
Console.WriteLine(Parse("hello", "=?not expected:this value's not null"));
An explanation of the regex & additional examples are available here:
https://regex101.com/r/YJ9qd3/1
Appending non-null/blank values to a URL's Query String
public void Main()
{
var url = "https://example.com?something=keepMe&foo=FooWasHere&bar=swapMeQuick";
var dict = new System.Collections.Generic.Dictionary<string, string>();
dict.Add("foo", null);
dict.Add("bar", "hello");
dict.Add("boo", "new");
Console.WriteLine(CreateUri(url, dict).ToString());
}
Uri CreateUri(string uri, IDictionary<string, string> parameters)
{
return CreateUri(new Uri(uri), parameters);
}
Uri CreateUri(Uri uri, IDictionary<string, string> parameters)
{
var query = HttpUtility.ParseQueryString(uri.Query); //https://msdn.microsoft.com/en-us/library/ms150046(v=vs.110).aspx; though returns HttpValueCollection
foreach (string key in parameters.Keys)
{
if (string.IsNullOrEmpty(parameters[key]))
{ //parameter is null or empty; if such a parameter already exists on our URL, remove it
query.Remove(key); //if this parameter does not already exist, has no effect (but no exception is thrown)
}
else
{ //parameter has a value; add or update the query string with this value
query.Set(key, parameters[key]);
}
}
var builder = new UriBuilder(uri);
builder.Query = query.ToString();
return builder.Uri;
}

C# Replace is causing Object Reference Not Found error

using "Replace" on the string clientNameStr causes an "Object Reference Not Found" error.
// Get client name
clientName = currentUser.GetValue("ClientName");
string clientNameStr = (string)clientName;
string clientURLStr = string.Empty;
clientURLStr = clientNameStr.Replace(' ', '-');
// clientURLStr = "ST9215-Stanic-Parts-Ltd";
If I substitute in the commented out string (and comment out the existing one) it works fine, so it must be something to do with the replace function, but what? Have tried it with both " and ' quote marks, to the same result.
Any help would be greatly appreciated.
Thanks, Oli.
That basically shows that currentUser.GetValue("ClientName") is returning a null reference1.
We can't tell what currentUser.GetValue("ClientName") does, but there are two options:
It's correctly returning null, and you should handle that
It shouldn't return null, and you need to fix it (possibly to throw an exception if it encounters this situation)
1 It's possible that it's returning a non-null reference and using a user-defined conversion to string in the next line which returns null - but unlikely. We can't tell for sure because we don't know the type of the clientName .
Probably clientName (and thus clientNameStr) is null. You cannot call methods on the null object, even if you know that it should be a string.
It's possible that currentUser.GetValue("ClientName") is returning null, thus throwing an error when trying to execute the Replace.
Better coding would be
clientName = currentUser.GetValue("ClientName");
string clientNameStr = clientName ?? "";
string clientURLStr = clientNameStr.Replace(' ', '-');

Categories

Resources