Write "?" in a string if a property is null - c#

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"))

Related

DataTable checking if null returns an error but not on variable declaration

I have this weird error.
On this code, as you can, I have a query on database, return it as DataTable and explicitly declared it null. Now I have a condition to check this if this is null and pass it to a string variable. Everything works fine. I receive an empty string. No exception found.
DataTable dtDateUploaded = _BL.GetRecordByDataTableResults();
dtDateUploaded = null;
string strUploadedDate = dtDateUploaded == null ? string.Empty :
dtDateUploaded.Rows[0].IsNull(0) ? string.Empty :
dtDateUploaded.Rows[0][0].ToString();
But when I used the same condition and pass it directly to a Label control for example (and not use a string variable), I get an object reference error. I wonder why do I get an object reference error if I just used the same code on my string variable above?
LblRecordCount.Text = "Record Uploaded last: " + dtDateUploaded == null ? string.Empty :
dtDateUploaded.Rows[0].IsNull(0) ? string.Empty :
dtDateUploaded.Rows[0][0].ToString();
And the weird part is that this works:
LblRecordCount.Text = "Record Uploaded last: " + strUploadedDate;
You get this error because, in the second example, the + operator has precedence over the == operator so you are trying to concatenate the "Record Uploaded last" string to a null variable.
Instead, in the first example, the = operator has lower precedence than the == operator and no error occurs because the ternary operators are evaluated before the assignment.
You should use brackets to group the ternary operators logic together
LblRecordCount.Text = "Record Uploaded last: " + (dtDateUploaded == null ? string.Empty :
dtDateUploaded.Rows[0].IsNull(0) ? string.Empty :
dtDateUploaded.Rows[0][0].ToString());
See MSDN on C# Operators

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";

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?

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

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.

Using null coalescing in foreach statement

Trying to figure out how to get the null coalescing operator to work in a foreach loop.
I'm checking to see what a string ends with and based on that, route it to a certain method. Basically what I want to say is....
foreach (String s in strList)
{
if s.EndsWith("d") ?? Method1(s) ?? Method2(s) ?? "Unknown file type";
}
In attempting to do this, of course you get the "Operator ?? cannot be used on type bool and type string." I know there is other ways to do it, just want to see how it can be done with null coalescing.
Have a good weekend.
#Richard Ev: Oh yes of course. Switch, if else, etc. Was just curious how it
could be handled
#Jon Skeet: After reading your comments it hit me, this is just bad! I am
interested in two file extensions basically. If a file ends with "abc" for
instance, send to method 1, if the file ends with "xyz" send to method 2. But
what if a file ends with an extension of "hij"...boom, you're done.
Thanks to Brian and GenericTypeTea as well for the thoughful input
I'm content calling it closed.
It looks like you want to use the normal ternary operator, not null coalescing. Something like:
(s.EndsWith("d") ? Method1(s) : Method2(s)) ?? "Unknown file type";
This is equivalent to:
string result;
if (s.EndsWith("d"))
result = Method1(s);
else
result = Method2(s);
if (result == null)
result = "Unknown file type";
return result;
I think you want a combination of the conditional (ternary) operator and the null coalescing operator:
foreach (String s in strList)
{
string result = (s.EndsWith("d") ? Method1(s) : Method2(s))
?? "Unknown file type";
}
In simple english, this will do the following:
If s ends with d, then it will try Method1.
If s does not end with d then it will try Method2.
Then if the outcome is null, it will use "Unknown file type"
If the outcome is not null, it will use the result of either A or B
I think the compiler gave you the appropriate answer, you can't.
Null coalescing is essentially this if statement:
if(x == null)
DoY();
else
DoZ();
A boolean value cannot be null, so you can't coalesce it like that. I'm not sure what your other methods return, but it seems like you want a simple || operator here.
You should first use the ?? null coalescing operator to guard against a null s reference. Then use the ? ternary operator to choose between Method1 and Method2. Finally use the ?? null coalescing operator again to provide the default value.
foreach (string s in strList)
{
string computed = s;
computed = computed ?? String.Empty;
computed = computed.EndsWith("d") ? Method1(s) : Method2(s);
computed = computed ?? "Unknown file type";
}

Categories