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 ?
CodePudding user response:
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;
CodePudding user response:
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;
}