What's the differences between .ToString() and + "" - c#

If I have a DateTime, and I do :
date.Year.ToString()
I get the Year as String. But Also if I do
date.Year + ""
the differences is only that the second one doesnt get an exception if there isn't the Date? (which i prefeer)

When you write date.Year + "" it will be compiled as a call to string.Concat(object, object):
String.Concat(date.Year, "")
Internally, the Concat method will call ToString on each (non-null) object.
Both approaches will throw a NullReferenceException if date is null. But you said date is of type DateTime. DateTime is a struct and so cannot be null.
If date is of type DateTime? and want to return an empty string if date is null then you can use this:
date.HasValue ? date.Value.Year.ToString() : ""

date.Year.ToString()
Won't work if date is null.
date.Year + ""
Works even if year is null as binary + operator substitutes null with a empty string.
This is what MSDN says about binary + operator concatenating two strings:
The binary + operator performs string concatenation when one or both operands are of type string. If an operand of string concatenation is null, an empty string is substituted. Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. If ToString returns null, an empty string is substituted.
More information on http://msdn.microsoft.com/en-us/library/aa691375%28VS.71%29.aspx

There is no difference if date.Year is not null.
In the second example the ToString() method is implicitly called on date.Year.

Related

Convert.ToString returns string.empty instead of null

I've found out a strange behaviour of Convert.ToString and I would like to understand, why it does behave like this.
Have a look at following code pieces:
string obj = null;
var str = Convert.ToString(obj);
Console.WriteLine(str); // CORRECT: returns null;
all good so far, but:
DBNull obj = DBNull.Value;
var str = Convert.ToString(obj);
Console.WriteLine(str); // ???: returns string.Empty ("")
and
object obj = null;
var str = Convert.ToString(obj);
Console.WriteLine(str); // ???: returns string.Empty ("")
It looks to me like a bug, because when i do a conversion to a string and the input is NULL the result should be default of a string, which is also NULL.
Convert.ToString has a String overload that does nothing:
Returns the specified string instance; no actual conversion is performed.
and its Object overload is defined thus:
The string representation of value, or String.Empty if value is null.
It might be a bit surprising, but there’s no reason to use Convert.ToString on a String expression in the first place.
That's documented behaviour
Convert.ToString Method (Object)
The string representation of value, or String.Empty if value is null.
Convert.ToString Method (String)
value is returned unchanged.

C# Null Conditional Operator with nullable datetime

I am trying to learn use the null conditional operator but can't seem to get it to work,
string datetest = DOInfolist[i].RentalItem.SimCard.DateIn[u].Value.ToShortDateString() ?? "Empty";
DateIn is a list of nullable DateTime (List<Datetime?>) .
I did debugging and all the values in DateIn[u] give null.
What am I doing wrong?
If all the values in the DateIn array are null, your code would throw a NullReferenceException.
You may use the null-propagation-operator here:
string datetest = DOInfolist[i].RentalItem.SimCard.DateIn[u]?.ToShortDateString() ?? "Empty";
This operator (?.) now returns a nullable string. If DateIn[u] has a value, ToShortDateString() is called and the operator returns a nullable string with the returned value.
If DateIn[u] is null the operator returns null, too.
You have a mistake. First check for null values by HasValue and use single ? not double ?? like the following snippet:
string datetest = DOInfolist[i].RentalItem.SimCard.DateIn[u].HasValue ? DOInfolist[i].RentalItem.SimCard.DateIn[u].ToShortDateString() : "Empty";

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.

Write "?" in a string if a property is null

How can I write the Startedate like "?" is Startdate is null
public DateTime? StartDate { get; set; }
public override string ToString()
{
return String.Format("Course {0} ({1} is an {2} course, will be given by {3}, starts on {4}, costs {5:0.00} and will have maximum {6} participants"
, Name
, CourseId
, CourseType
, Teacher
, (StartDate == null ? "?" : StartDate)
, Price
, MaximumParticipants);
}
C# 6 lets you write this without ternary operator, like this:
StartDate?.ToString("dd-MM-yyyy") ?? "?"
?. will conditionally execute ToString only if StartDate is not null. Null coalesce operator ?? will complete the job by providing "?" string as a replacement for null value.
You can go further and replace String.Format with interpolating string, like this:
return $"Course {Name} ({CourseId} is an {CourseType} course, will be given by {Teacher}, starts on {StartDate?.ToString("dd-MM-yyyy") ?? "?"}, costs {Price:0.00} and will have maximum {MaximumParticipants} participants";
Both sides of the ternery operator need to be the same type. From the documentation:
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
So you can simply convert your date to a string (note the formatting is up to you):
(StartDate == null ? "?" : StartDate.Value.ToString("dd-MM-yyyy"))
You could tweak your existing code
(StartDate == null ? "?" : StartDate.ToString())
Or leverage Nullable<T> .HasValue
(StartDate.HasValue ? StartDate.ToString() : "?")
The point is, ?: requires the same type for both conditions.
you can use IsNullOrEmpty() function it will cover null or empty date
(IsNullOrEmpty(StartDate) ? "?" : StartDate.ToString("dd-MM-yyyy"))

converting string to datetime in C# on null value exception

I use the below code
extensionRequest[i].EndDate = DateTime.Parse(dsResult.Tables[0].Rows[i]["ActualEndDate"].ToString());
extensionRequest[i].ExtendedEndDate = DateTime.Parse(dsResult.Tables[0].Rows[i]["ExtendedEndDate"].ToString());
extensionRequest[i].ReceivedDate =Convert.ToDateTime(dsResult.Tables[0].Rows[i]["dReceivedOn"].ToString());
this works fine when values are coming from the DB
but when NULL values are returned it throws an exception!!
Should i check values for all three values like the code below
if (dsResult.Tables[0].Rows[i]["dReceivedOn"].ToString()==null){
extensionRequest[i].ReceivedDate="";
}
else{
extensionRequest[i].ReceivedDate =Convert.ToDateTime(dsResult.Tables[0].Rows[i]["dReceivedOn"].ToString());
}
or i should assign all dates to null on exception?!
is there any other way to do in single line? like tryparse or something?
I'll try being creative. You can create a Nullable TryParse as an Extension Method edition:
public static DateTime? TryParseNullable(this DateTime dateTime, string val)
{
DateTime outValue;
return DateTime.TryParse(val, out outValue) ? (DateTime?) outValue : null;
}
and then use:
extensionRequest[i].EndDate = DateTime.TryParseNullable(dsResult.Tables[0].Rows[i]["ActualEndDate"].ToString());
and that can be your one liner.
You can use DateTime.TryParse() method which returns true on successfull conversion otherwise returns false.
Note: calling ToString() on null throw NullReferenceException hence you need to check for null value before conversion.
Try This:
if(dsResult.Tables[0].Rows[i]["ActualEndDate"] != null)
DateTime.TryParse(dsResult.Tables[0].Rows[i]["ActualEndDate"].ToString(),
out extensionRequest[i].EndDate);
You can check if value is null like this
extensionRequest[i].EndDate = Convert.IsDbNull(dsResult.Tables[0].Rows[i]["ActualEndDate"]) ? null : Convert.ToDateTime(dsResult.Tables[0].Rows[i]["ActualEndDate"]);
I'm sure .ToString() is not required.
It will be more readable if you cache a row to the local variable:
var row = dsResult.Tables[0].Rows[i];
...
extensionRequest[i].EndDate = Convert.IsDbNull(row["ActualEndDate"]) ? null : Convert.ToDateTime(row["ActualEndDate"]);
Be sure .EndDate and others allow null values. In other words, that is DateTime?

Categories