c# get and set accessors datetime - c#

I am receiving unreachable code detected in my properties. This worked for regular string fields but not for DateTime data type.
private DateTime m_RenewalDate;
public DateTime M_RenewalDate
{
get { return m_RenewalDate != null ? m_RenewalDate : DateTime.MinValue; }
set { m_RenewalDate = value; }
}
this is my sqldatareader
reader.GetDateTime(reader.GetOrdinal("M_RENEWALDATE"))

DateTime is a value type, and can not be null. Therefore, the code in the getter is unreachable:
return m_RenewalDate != null ? // always evaluates to true
m_RenewalDate : // and therefore always returns this
DateTime.MinValue; // The code never hits this case.
If your field in the database can be null, perhaps you want to declare the property as a nullable DateTime: DateTime?.

DateTime is a value type and cannot be null. To compare with a null value in the database, use DBNull.Value

As driis said in his answer, m_RenewalDate == null is always false as DateTime is a value type and things declared to be value types cannot be null.
To have the get the behavior of returning DateTime.MinValue from M_RenewalDate in the case that M_RENEWALDATE is null your reader code should look more like this
object renewalDate = reader.GetValue(reader.GetOrdinal("M_RENEWALDATE"));
if (Equals(renewalDate, DBNull.Value))
{
yourObject.M_RenewalDate = DateTime.MinValue;
}
else
{
yourObject.M_RenewalDate = (DateTime) renewalDate;
}

Related

csharp Value of '01/01/0001 00:00:00' is not valid how to handle?

if (File.Exists(settingsFile))
{
string[] lines = File.ReadAllLines(settingsFile);
if (lines.Length > 0)
{
trackBarHours.Value = Convert.ToInt32(optionsfile.GetKey("trackbarhours"));
trackBarMinutes.Value = Convert.ToInt32(optionsfile.GetKey("trackbarminutes"));
trackBarSeconds.Value = Convert.ToInt32(optionsfile.GetKey("trackbarseconds"));
savedMilliseconds = Convert.ToInt32(optionsfile.GetKey("milliseconds"));
dateTimePicker1.Value = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue"));
richTextBox1.Text = optionsfile.GetKey("result");
}
}
because the key "timetargetvalue" is not yet created in the settingsFile because i didn't saved it yet for the first time the value of the key of "timetargetvalue" is '01/01/0001 00:00:00'
in that case that there is no yet the key hwo can i handle the datetime exception ?
dateTimePicker1 is a DateTimePicker control.
the exception is on the line :
dateTimePicker1.Value = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue"));
System.ArgumentOutOfRangeException: 'Value of '01/01/0001 00:00:00' is not valid for 'Value'. 'Value' should be between 'MinDate' and 'MaxDate'.
Parameter name: Value'
what should i check against of so it will not throw the exception ?
DateTimePicker.Value must be above DateTimePicker.MinimumDateTime, which is 'January 1, 1753'.
When you haven't set the timetargetvalue, it will resolve to '01/01/0001 00:00:00', as you have seen, which is too early.
So you need to check the value before assigning it to DateTimePicker.Value.
You can do it like this:
DateTime tempDateTime = Convert.ToDateTime(optionsfile.GetKey("timetargetvalue");
dateTimePicker1.Value = tempDateTime >= DateTimePicker.MinimumDateTime ? tempDateTime : DateTimePicker.MinimumDateTime;
When dealing with a Struct such as DateTime that does not have any value we need to consider that this is not a class and can not be set to null. It must always have some value. (see https://learn.microsoft.com/en-us/dotnet/api/system.datetime?view=net-7.0)
The exception mentions in a round about way that the range of acceptable values is between dateTimePicker1.MinDate and dateTimePicker1.MaxDate so one option is to check if your value is within this range. But it's unlikely to be the best option. (see https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.datetimepicker.mindate?view=windowsdesktop-6.0)
I'm pretty sure that DateTime default value is equal to that of DateTime.Min but if you really wanted to check if the value is default then I would suggest comparing it to default(DateTime) would be better.
This pretty much covers the use of DateTime and value defaults when null is not an option. Which brings up a possibly more desirable option. Encapsulation.
We could instead encapsulate the DateTime struct into a Nullable class. The encapsulating class will be nullable and will also be able to present the encapsulated value through a property called Value. (see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types)
There are two ways to declare such a Nullable class, both of which compile to the same thing:
Nullable<DateTime> myNullableDate = null;
DateTime? anotherNullableDate = null;
Since the DateTime is encapsulated in a Nullable object we can start using a null reference check. We can also call a method on Nullable called HasValue which returns a bool (True if it has a value).
EDIT: I notice that you're not doing any checks before trying to parse the DateTime and then directly setting it into the DateTimePicker.Value which can accept a null value. (although setting null won't clear a previously set value).
As such perhaps what you might want to do is handle the scenario a bit better and then use a DateTime.TryParse() instead. (see https://learn.microsoft.com/en-us/dotnet/api/system.datetime.tryparse?view=net-7.0)
e.g. (not the most optimized code, but I think it's easier to follow along in a more verbose form)
private DateTime? LoadDateFromOptions(string key)
{
var rawValue = optionsfile.GetKey(key);
if (!string.IsNullOrEmpty(rawValue))
{
return null;
}
DateTime dateValue;
bool isSuccess = DateTime.TryParse(rawValue, out dateValue);
if (isSuccess)
{
return dateValue;
}
else
{
return null;
}
}
and then instead of having that exception you can load the value optionally a bit more like this:
var timeTarget = LoadDateFromOptions("timetargetvalue");
if (timeTarget != null)
{
dateTimePicker1.Value = timeTarget;
}

Getting Time from DateTime

This is confusing, all I want is the Time from DateTime ?
here is my code:
clsdbo_RR.DateRecd = reader["DateRecd"] is DBNull ? null : (DateTime?)reader["DateRecd"];
clsdbo_RR.TimeRecd = reader["TimeRecd"] is DBNull ? null : reader["TimeRecd"].ToString("hh:mm:ss");
My date appears as date correctly but the time is not showing up?
private Nullable<DateTime> m_TimeRecd;
public Nullable<DateTime> DateRecd
{
get
{
return m_DateRecd;
}
set
{
m_DateRecd = value;
}
}
I strongly suspect that your reader["TimeRecd"] returns object, that's why you need to cast it to DateTime (or DateTime? as you did) first before you call ToString method. Without casting, it probably calls object.ToString method, not DateTime.ToString.
If your clsdbo_RR.TimeRecd is string, you just need to use (DateTime?)reader["TimeRecd"].ToString("hh:mm:ss") instead like;
clsdbo_RR.TimeRecd = reader["TimeRecd"] is DBNull ?
null : (DateTime?)reader["TimeRecd"].ToString("hh:mm:ss");

Assert Variable is not Null

I have a Variable with type DateTime?
In a Function I check it for being null and want to use it afterwards without always having to ?. every call. In e.g. Kotlin the IDE recognizes a check like that and asserts that the variable cannot be null afterwards. Is there a way to do this in C#?
DateTime? BFreigabe = getDateTime();
if (BFreigabe == null) return false;
TimeSpan span = BFreigabe - DateTime.Now;
//Shows Error because it.BFreigabe has the type DateTime?, even though it can't be null
Edit:
When using
TimeSpan span = BFreigabe.Value - DateTime.Now;
instead it works in this case because .Value doesn't have nullsafety at all. However, considering that this would compile even without the null check and just produce an error, the general question still remains. How can one persuade C# that a former nullable variable isn't nullable any more?
Edit 2
Casting DateTime on the Variable works.
TimeSpan span = (DateTime)BFreigabe - DateTime.Now;
Still not as safe as in Kotlin, but similar enough.
If you have the previous check, you can access the value. Nullable types always have two properties: HasValue and Value.
You could either cast to DateTime (Without the ?) or use the value property.
DateTime? BFreigabe = getDateTime();
if (!BFreigabe.HasValue == null)
return false;
TimeSpan span = BFreigabe.Value - DateTime.Now;
Or store the nullable variable in a non nullable variable:
DateTime? BFreigabe = getDateTime();
if (BFreigabe.HasValue == null)
{
DateTime neverNull = BFreigabe.Value;
TimeSpan span = neverNull - DateTime.Now;
}
This will get full editor support and guarantee that there is no NullReferenceExcpetion.
EDIT: Because your question states Assert. Assert usually means that we will throw an exception if the state is invalid.
In this case, omit the check for nullness. If you access var.Value while var is null, this will throw a NullReferenceException. This moves the responsibility to the caller.
Another option would be to not use the nullable variable. Either by converting it (see the second listing) or by not accepting Nullable types as a parameter.
function TimeSpan Calc(DateTime time)
{
// here we know for sure, that time is never null
}
How about this?
DateTime? BFreigabe = getDateTime();
if (!BFreigabe.HasValue) return false;
DateTime BFreigabeValue = BFreigabe.Value;
TimeSpan span = BFreigabeValue - DateTime.Now;
Try to convert NULL value to any value, that is irrelevant.
DateTime? BFreigabe = getDateTime();
if (BFreigabe == null) return false;
TimeSpan span = (BFreigabe??DateTime.Now) - DateTime.Now;

DateTime null values

I have the following code that is supposed to check that a value in a data reader is not null. If it is then the method should return a null value or null DateTime for use later.
private static DateTime safeGetDateTime(OleDbDataReader dr, int idx)
{
if (!dr.IsDBNull(idx))
return dr.GetDateTime(idx);
else return DateTime.MinValue;
}
I have tried just returning null but as the methods return type is "DateTime", this did not work. I then tried to return DateTime.MinValue if a null is picked up by the datareader. This has given me the following error:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
Any help is appreciated.
You get this error because of DateTime.MinValue differeneces in CLR and SQL server.
I suggest you to use Nullable Type
Let the method return a Nullable<DateTime>, then you can return null:
private static DateTime? safeGetDateTime(OleDbDataReader dr, int idx)
{
if (!dr.IsDBNull(idx))
return dr.GetDateTime(idx);
else
return null;
}
You still have to check the return value, your error suggests that you are using this value in another sql query as parameter, you have to assign DBNull.Value in the null-case.
DateTime? date = safeGetDateTime(reader, columnOrdinal);
yourSqlParameter.Value = date.HasValue ? (object)date.Value : DBNull.Value;
The error must come from you assigning DateTime.MinValue to a SqlDateTime parameter.
DateTime.MinValue:
The value of this constant is equivalent to 00:00:00.0000000, January 1, 0001.
SqlDateTime.MinValue
The minimum valid date for a SqlDateTime structure is January 1, 1753.
So if you are going to use the return of this method in a SqlDateTime parameter, you can try returning SqlDateTime.MinValue:
return (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
Alternatively, you can try using DateTime? as the returning type, so you can return null
You can keep safeGetDateTime just as it is, but when you write the value back to the database, you should check if it is the DateTime.MinValue. If it is, then you should write a null value to the database.
if (value == DateTime.MinValue)
{
comm.Parameters.AddWithvalue("#mydate", null);
}
else
{
comm.Parameters.AddWithValue("#mydate", value);
}

using Nullable DateTime in C#

I wanted to assign null value to DateTime type in c#, so I used:
public DateTime? LockTime;
When LockTime is not assigned LockTime.Value contains null by default.
I want to be able to change LockTime.Value to null after it has been assigned other value.
No, if LockTime hasn't been assigned a value, it will be the nullable value by default - so LockTime.Value will throw an exception if you try to access it.
You can't assign null to LockTime.Value itself, firstly because it's read-only and secondly because the type of LockTime.Value is the non-nullable DateTime type.
However, you can set the value of the variable to be the null value in several different ways:
LockTime = null; // Probably the most idiomatic way
LockTime = new DateTime?();
LockTime = default(DateTime?);
You could assign null directly to the variable (the Value property is readonly and it cannot be assigned a value):
LockTime = null;
Have you tried LockTime = null?
The Value porperty is readonly, so you can't assign a value to it. What you can do is to assign null to the LockTime field:
LockTime = null;
However, this will create a new DateTime? instance, so any other pieces of code having a reference to the original LockTime instance will not see this change. This is nothing strange, it's the same thing that would happen with a regular DateTime, so it's just something your code has to deal with gracefully.
DateTime? nullableDT = null;
Console.WriteLine("{0}\t{1}", nullableDT.HasValue, nullableDT);
nullableDT = DateTime.Now;
Console.WriteLine("{0}\t{1}", nullableDT.HasValue, nullableDT);
nullableDT = null;
Console.WriteLine("{0}\t{1}", nullableDT.HasValue, nullableDT);
/*
False
True 30.07.2010 11:17:59
False
*/
You can define the variable this way:
private Nullable<DateTime> _assignedDate;
_assignedDate = DateTime.Now;
and then assign a null value:
_assignedDate = null;

Categories

Resources