can this trim code ever fail? - c#

I recently bumped into an exception in my code because I was trimming a null string.
I replaced it with the following:
SomeValue = (SomeString ?? "").Trim();
Can this code ever fail?
Thanks.
Note: I know I can add a try/catch; I'm just looking to make this line fail-proof without using a try/catch.

This will not fail (ie. throw a NullReferenceException), assuming SomeString is indeed a string.
You could achieve the same in many ways:
SomeValue = (SomeString == null)?string.Empty:SomeString.Trim();

It's not the way I would have done it, but no, this shouldn't ever fail now.
I'd probably write an extension method that calls trim after checking for null. Something like this:
public static string NullTrim(this String str) {
if(str == null) {
return string.Empty;
}
return str.Trim();
}
This allows all of the following to compile and execute without error:
"".NullTrim();
" test ".NullTrim();
((string)null).NullTrim();

Well if it was failing because of NullReferenceException, then now it will definitely not fail because of that. As for the rest, I cannot say without context.

Related

How are null values in C# string interpolation handled?

In C# 6.0, string interpolations are added.
string myString = $"Value is {someValue}";
How are null values handled in the above example? (if someValue is null)
EDIT:
Just to clarify, I have tested and am aware that it didn't fail, the question was opened to identify whether there are any cases to be aware of, where I'd have to check for nulls before using string interpolation.
That's just the same as string.Format("Value is {0}", someValue) which will check for a null reference and replace it with an empty string. It will however throw an exception if you actually pass null like this string.Format("Value is {0}", null). However in the case of $"Value is {null}" that null is set to an argument first and will not throw.
From TryRoslyn, it's decompiled as;
string arg = null;
string.Format("Value is {0}", arg);
and String.Format will use empty string for null values. In The Format method in brief section;
If the value of the argument is null, the format item is replaced with
String.Empty.
It seems that the behavior depends on which underlying formatting methods are called, and the implementation of these can change over time. If you get a null formated into the string such as "(null)", it is not sure this will stay the same over several years. In some newer version of .NET it can start throwing an exception.
So I think the most safe approach is to make some condition to avoid using the null. Write a simple ternary operation like:
int? someValue = 5;
var valueStr = (someValue is not null) ? someValue.ToString() : string.Empty;
var myString = $"Value is {valueStr}";
It is an extra line of code, but at least the behavior is controlled.

Why isn't the empty string an identity of concatenation?

I was reading this blog post by Eric Lippert http://ericlippert.com/2013/06/17/string-concatenation-behind-the-scenes-part-one/#more-1228 and became aware that the empty string is not an identity of concatenation in C#. I haven't run into a situation that made me aware this was the case and always just assumed it was an identity. I assume there is some good reason why
string NullString = null;
NullString = NullString + String.Empty; // results in and empty string, not null
results in an empty string rather than null, what is that reason? Why is there no identity of string concatenation? Was it made that way for convenience or practicality?
The documentation for String.Concat explains this behavior:
An Empty string is used in place of any null argument.
Basically, the String.Concat method was designed to exhibit this behavior.
Was it made that way for convenience or practicality?
While only the framework design team could directly answer this, this behavior does has some practical benefits. This behavior allows you to concatenate strings with null and not create null results, which reduces the number of explicit null checks required in most code. Without this behavior, someString + "abc" would require null checking, wheras with it, a non-null value is guaranteed.
I must admit that i don't understand "the identity of string concatenation". However, the reason why null + string.Empty is not null but string.Empty is:
because it was implemented in this way.
Have a look:
public static string Concat(string str0, string str1)
{
if (string.IsNullOrEmpty(str0))
{
if (string.IsNullOrEmpty(str1))
{
return string.Empty;
}
return str1;
}
else
{
if (string.IsNullOrEmpty(str1))
{
return str0;
}
int length = str0.Length;
string text = string.FastAllocateString(length + str1.Length);
string.FillStringChecked(text, 0, str0);
string.FillStringChecked(text, length, str1);
return text;
}
}
This is also documented:
The method concatenates str0 and str1; it does not add any delimiters.
An Empty string is used in place of any null argument.
If you ask for the why. I assume because it's safer this way. If you want to concat two strings and one of both is null, why should null be favored instead of string.Empty?
Because it uses a contract, the purpose of which is described at Code Contracts.
From String.Concat:
Contract.Ensures(Contract.Result<string>() != null);
Note that NullString + NullString also returns an empty string.

equivalent shorthand

What is the shorthand equivalent to the following snippent of code?
if (strValue == ""){
throw new Exception("Mandatory 'strValue' parameter empty");
}
It's probably as short as you can get it, barring removal of spaces and braces (and sacrificing readability in the process).
As for correctness... this might be better:
.NET 4.0:
if (string.IsNullOrWhiteSpace(strValue)){
throw new ArgumentException("Mandatory 'strValue' parameter empty");
}
.NET < 4.0:
if (string.IsNullOrEmpty(strValue)){
throw new ArgumentException("Mandatory 'strValue' parameter empty");
}
Also note that it is bad practice to simply throw Exception - it is much better to select an appropriate exception class from the BCL if one exists, or a custom one if one doesn't. (thanks #djacobson)
if(strValue=="")throw new Exception("Mandatory 'strValue' parameter empty");
All you can do is remove the braces and spaces :)
With a null check, which I think you want, and using ArgumentException:
ThrowIfNullOrEmpty(strValue, "strValue");
...
private void ThrowIfNullOrEmpty(string parameterValue, string parameterName)
{
if String.IsNullorEmpty(parameterValue)
{
throw new ArgumentException("Mandatory 'strValue' parameter empty",
parameterName);
}
}
Obviously only useful if you're doing this more than a few times.
You could use Code Contracts.
You could also use string.IsNullOrWhitespace()
Contract.Requires(string.IsNullOrEmpty(strValue), "** fancy localized message here ***");
It's already short. Instead of doing strValue == "", I'd do String.Empty or String.NullOrEmpty, I can't remember which one is available in .NET
Does not get much shorter, but if want less lines then:
if (String.IsNullOrWhitespace(strValue)) throw new Exception("Mandatory 'strValue' parameter empty");
You're pretty much as short as you can get. I recommend using the IsNullOrEmpty String function for checking for an empty string. Also, it may be suitable to be more specific in your exception handling and throw an ArgumentException.
if (String.IsNullOrEmpty(strValue)) { throw new ArgumentException("strValue must not be null or empty") };
Assuming that you're trying to write more defensive code, you could use Trace.Assert
Trace.Assert(strValue != "", "Mandatory 'strValue' parameter is not empty");
Or you could use the Fluent Validation library to encapsulate more complicated validation.

Querystring - Add values to querystring in c#

How can I add values to querystring?
I'm trying to do this:
String currurl = HttpContext.Current.Request.RawUrl;
var querystring = HttpContext.Current.Request.QueryString.ToString();
var PrintURL = currurl + (String.IsNullOrEmpty(querystring)) ?
HttpContext.Current.Request.QueryString.Add("print", "y") : string.Empty;
But I keep getting this error:
Cannot implicitly convert type 'string' to 'bool'
all i'm trying to do is get current url and add ?pring=y to querystring
Well, the first problem can be solved using this instead:
var PrintURL = currurl + (String.IsNullOrEmpty(querystring) ?
HttpContext.Current.Request.QueryString.Add("print", "y") : string.Empty);
All that's changed from your original code is simply moving the closing paren from (String.IsNullOrEmpty(querystring)) (where it was unnecessary) to the end of the ?: clause. This makes it explicitly clear what you're trying to do.
Otherwise, the compiler tries to concatenate the result of String.IsNullOrEmpty(querystring) (which is a bool) to currUrl -- incorrect, and not what you intended in the first place.
However, you've got a second problem with the HttpContext.Current.Request.QueryString.Add("print", "y") statement. This returns void, not a string. You'll need to modify this part of your ternary expression so that it returns a string -- what are you trying to do?
HttpContext.Current.Request.QueryString.Add("print", "y") returns void, not a string, so you can't use that call in the ternary expression. Plus, adding to the querystring on the Request won't affect your HTTPResponse, and I'm assuming that's what you want to do. You need to craft the new URL and use response.redirect to have the browser load the new url with the updated querystring.
i figured it out.
String currurl = HttpContext.Current.Request.Url.ToString();
String querystring = null;
// Check to make sure some query string variables
// exist and if not add some and redirect.
int iqs = currurl.IndexOf('?');
if (iqs == -1)
{
String redirecturl = currurl + "?print=y";
}
not sure if this is the cleanest way but it works.
thanks all for help
There's a couple things wrong here with what you're trying to do.
The first thing is that the QueryString collection is a NameValueCollection. The Add method has a void return. So even trying to assign the result of QueryString.Add isn't going to work.
Second, you can't modify the QueryString collection. It's read-only. There's a response over on Velocity Reviews that talks to exactly what you're trying to do. Instead of trying to modify the query string, you should redirect the user with the new value.
currurl + (String.IsNullOrEmpty(querystring)
has to return a boolean so condition has to be different.
First problem is you need brackets around your statement that is using the ?:
var PrintURL = currurl + ((String.IsNullOrEmpty(querystring)) ? HttpContext.Current.Request.QueryString.Add("print", "y") : string.Empty);
The next problem is that HttpContext.Current.Request.QueryString.Add does not return anything so one side of the : returns void where the other returns and empty string.

String comparision not working correctly?

I'm using this library to hook keys and I have some problems with comparing e.KeyCode.ToString() with same string.
I have variable which is string equivalent of
Keys.Oemtilde ->
Program.KeyboardTradeHotkey = "Oemtilde";
I keep it in string because I read that string from xml file and I can't seem to get any way to convert string to Keys.
If i use it this way:
if (e.KeyCode.Equals(Keys.Oemtilde)) {
Logging.AddToLog("[Keyboard][Check] " + e.KeyCode);
} else {
// failed to catch - executes else
Logging.AddToLog("[Keyboard][PRESS]");
}
It works fine and: Logging.AddToLog("[Keyboard][Check] " + e.KeyCode); is executed.
If i use it:
if (e.KeyCode.ToString() == Program.KeyboardTradeHotkey) {
Logging.AddToLog("[Keyboard][Check] " + e.KeyCode);
} else {
// failed to catch - executes else
Logging.AddToLog("[Keyboard][PRESS]");
}
It executes else clause. It seems like String Compare doesn't really works in this case even thou both string (e.KeyCode.ToString() and Program.KeyboardTradeHotkey are the same.
What can be the reason for this?
another change make use of string.Equals function to compare string
string1.Equals(string2)
I think it is because KeyCode.ToString() doesn't return what you expect it to return. Look at the view in a Watch.
Without having to look at the library that you are using the first (working) code sample looks like it is comparing enum values, so it is returning a number instead of a string.
The difference between == and .Equals() is because of the differences between reference types and value types. This link gives examples of the different results: Comparison of == and .Equals()
I also agree with pranay_stacker.

Categories