Cannot implicitly convert 'System.TimeSpan?' to 'System.TimeSpan' - c#

The below code works fine :
DateTime d1 = DateTime.Now;
DateTime d2 = DateTime.Now.AddDays(-1);
int d3 = (int)(d1 - d2).TotalDays;
But what if I define DateTime as DateTime? :
DateTime? d1 = DateTime.Now;
DateTime? d2 = DateTime.Now.AddDays(-1);
int d3 = (int)(d1 - d2).TotalDays;
underlined red with error
Cannot implicitly convert 'System.TimeSpan?' to 'System.TimeSpan'
Is it possible to get the difference of number of days between two datetimes that are defined as nullable?

Well yes, but you need to use the Value property to "un-null" it:
int d3 = (int)(d1 - d2).Value.TotalDays;
However, you should consider the possibility that either d1 or d2 is null - which won't happen in your case, but could in other cases. You may want:
int? d3 = (int?) (d1 - d2)?.TotalDays;
That will give a result of null if either d1 or d2 is null. This is assuming you're using C# 6, of course - otherwise the ?. operator isn't available.
(You could use GetValueOrDefault() in the first case as suggested by user3185569, but that would silently use an empty TimeSpan if either value is null, which feels unlikely to be what you want.)

Yes, using GetValueOrDefault():
DateTime? d1 = DateTime.Now;
DateTime? d2 = DateTime.Now.AddDays(-1);
int d3 = (int)(d1 - d2).GetValueOrDefault().TotalDays;
d1 - d2 return Nullable TimeSpan which doesn't directly contains a property called TotalDays. But using GetValueOrDefault() you can return a TimeSpan object and get 0 Total Days if the value was NULL
If you do really expect Null Values, it is better to differentiate between 0 days (What the above approach returns) and and invalid operation (date - null), (null - date) and (null - null). Then you might need to use another approach:
int? d3 = (int) (d1 - d2)?.TotalDays;
Or if you're using a version prior to C# 6 :
int? d3 = d1.HasValue && d2.HasValue ? (int)(d1 - d2).Value.TotalDays : new int?();

use long and convert
long x
System.TimeSpan y= new TimeSpan(x);

Related

How can I subtract an object in dotnet core using the minus symbol? Similar to DateTime

DateTimes in dotnet can be subtracted from each other using the symbol (-) and getting a span as a result. How can I replicate the behavior of DateTime to use the - symbol but for my own custom object
For example
Datetime a = DateTime.UtcNow();
Datetime b = DateTime.UtcNow();
Span c = b-a;
Thanks
What you are looking for is called operator overloading. Check the reference here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading
Of course, the implementation will totally depend on the logic you need to put beneath the operator. And of course, you are not bound to return the same type as your operands.
The example in your post is implemented like this:
public static TimeSpan operator -(DateTime d1, DateTime d2) {
return new TimeSpan(d1.InternalTicks - d2.InternalTicks);
}
See here: https://referencesource.microsoft.com/#mscorlib/system/datetime.cs,1503

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;

Problems with converting type int? to int. Missing a cast?

I am trying to pull a date from a separate program and use it to determine the expiration dates of contracts. I have called int's for the month day and year and then used DateTime to assign to another var.
I am fairly new to C# and and can't find a work around for the error I get with this block. The errors tell me that it cannot implicitly convert int? to int, when I use an int? var to declare the day month and year it then shifts the error down to the DateTime line.
This probably needs to be structured differently but I can't figure out what that way would be.
private Instrument m_instr = null;
private void m_getInstrDetails(Instrument instr)
{
m_ContractName = instr.Name.ToString();
m_type = instr.Product.Type.ToString();
m_prod = instr.Product.ToString();
m_SmallestTickIncrtement = instr.InstrumentDetails.SmallestTickIncrement;
//month calc
int month = m_instr.InstrumentDetails.ExpirationDate.Month;
int day = m_instr.InstrumentDetails.ExpirationDate.Day;
int year = m_instr.InstrumentDetails.ExpirationDate.Year;
m_expDate1 = new DateTime(year, month, day);
A nullable integer (int?) cannot be cast to a traditional integer (int) since there are scenarios where one might be null, and you'll need to determine how you want to handle such occasions.
Consider Parsing or Using a Default Value
You need to determine what you want to occur when your nullable value is null. Nullable integers by default expose a HasValue property, which you can use to determine as a default or you could consider using the null-propagation operator to handle this :
// This will use the expiration date if it exists, otherwise it will use 1
int month = m_instr.InstrumentDetails.ExpirationDate?.Month ?? 1;
Another option involves setting an initial value and using the int.TryParse() method to update the value prior to use :
int month = 1;
int.TryParse(m_instr.InstrumentDetails.ExpirationDate?.Month, out month);
Considering Throwing an Exception
If you don't want to allow these types of scenarios to occur and using some default value isn't feasible, you could consider just throwing an exception :
if(!month.HasValue) { throw ArgumentException("month"); }
You can allow this to bubble up to the appropriate location and handle it accordingly within your application (i.e. notify the user, log the problem, etc.)
int? is a Nullable-type, that means, that your int also could be null.
You get the value by
int? month = m_instr.InstrumentDetails.ExpirationDate.Month;
int month = month.Value;
you could check, if month is not null by
bool monthIsNotNull = month.HasValue;
because you could get an exception when trying to initialize the DateTime-variable when month is null - or at least, when trying to get int via month.Value and month is null
the DateTime-constructor wants DateTime(int year, int month, int day) - he doesn't want to get e.g. a month that's null
Assuming that the ExpirationDate.<properties> are your int? s, if the concern is whether or not there is an ExpirationDate, shouldn't you see if that is null instead? Then you could just use regular ints as properties of an ExpirationDate object.:
private void m_getInstrDetails(Instrument instr)
{
m_ContractName = instr.Name.ToString();
m_type = instr.Product.Type.ToString();
m_prod = instr.Product.ToString();
m_SmallestTickIncrtement = instr.InstrumentDetails.SmallestTickIncrement;
if(InstrumentDetails.ExpirationDate != null)
{
//if you change the .Month, .Day, and .Year to int, and test against
//ExpirationDate, this will work fine
//month calc
int month = m_instr.InstrumentDetails.ExpirationDate.Month;
int day = m_instr.InstrumentDetails.ExpirationDate.Day;
int year = m_instr.InstrumentDetails.ExpirationDate.Year;
m_expDate1 = new DateTime(year, month, day);
}
}

Nullable DateTime in C#

I have two questions related to DateTime assingments
DateTime? y = 1 == 1 ? null: DateTime.MaxValue;
DateTime? y = null; // assignment works as expected
Why the first assignment issues error of type conversion between null and DateTime?
Which is the preferred way for null assignments of DateTime? in c#.
DateTime? x = default(DateTime?); //prints null on console
DateTime? x = null; // prints null on console
DateTime? x = DateTime.MinValue; //print 01/01/0001
The second statement DateTime? y = null; is only an assignment of null to a nullable object.
Whereas the first is a conditional assignment, which assigns some value for the true state and some other value for the false; Here you are using the conditional operator for evaluating the condition. according to MSDN first_expression (executes if true) and second_expression*(executes if false)* must be of same type or an implicit conversion must exist from one type to the other. In our case both are different so The simple solution is doing an explicit conversion as like this:
DateTime? y = 1 == 1 ?(DateTime?) null : DateTime.MaxValue;
A1. Because in ternary operator both expressions/results should be of same type.
Acc. to MSDN 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.
In your question, null and DateTime.MinValue do not match and hence the error conversion between null and DateTime.
You can do
DateTime? y = 1 == 1 ? null : (DateTime?)DateTime.MaxValue;
This way both answers return an answer whose type is DateTime?.
A2. Normally there is no said/preferred way of assigning this. This depends on user convention. All three are good and depend on user requirements.
Because ?: Operator operator expects same type on both sides.
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 solution will be like below:
DateTime? y = 1 == 1 ? (DateTime?)null : DateTime.MaxValue;
And for second question, this will be good way for null assignment
DateTime? x = null;
DateTime? y = 1 == 1 ? null: DateTime.MaxValue;
This statement is giving an assignment error not because of the null assignment to a variable it is because of using null assignment in ternary operator and as you are using a class type here you the ternary operator do not lead you to do this illegal stuff as per CLR specifications mentioned,It might give you a straight compilation error.
//Which is the preferred way for null assignments of DateTime? in c#.
DateTime? x = default(DateTime?); //prints null on console
DateTime? x = null; // prints null on console
DateTime? x = DateTime.MinValue; //print 01/01/0001
As per Specifications and guidelines provided the Class Types should not be assigned null in any scenario so as per standard you can use the min value(though you can use default value too but it might effect in type conversions when needed)
The second one that you mentioned. You need to cast null value in this time asmensioned by Sir Nikhil Agrawal.
Ternary
int y = 1;
DateTime? dt3 = y == 1 ? (DateTime?)null : DateTime.MinValue;
Traditional way
DateTime? dt3 = null;
if (y == 1)
dt3 = null;
else
dt3 = DateTime.MinValue;
if you want to cast null to nullable datetime then you can use
DateTime? dt = (DateTime?)null;

how can i remove the value from a DateTime?

i have an existing DateTime? object that has a datetime in it. I want to remove the datetime value from it so when you ask "HasValue" it returns false?
Nullable<T>is immutable, so you will have to reassign the variable to a different value to be able to change / remove the underlying value. This makes sense since it is a value-type (although a special one at that); value-types are normally immutable in the framework. You will notice that neither theValuenor theHasValue property forNullable<T>has a setter.
DateTime? nullableDt = DateTime.Now;
Console.WriteLine(nullableDt.HasValue); //true
nullableDt = null;
Console.WriteLine(nullableDt.HasValue); //false
or
nullableDt = new DateTime?();
Set it to null.
If you have
DateTime? value = DateTime.Now;
then call
value = null;
Why not just set it back to null?
DateTime? d = null;
System.Diagnostics.Debug.WriteLine("HasValue1 = {0}", d.HasValue); //False
d = DateTime.Now;
System.Diagnostics.Debug.WriteLine("HasValue2 = {0}", d.HasValue); //True
d = null;
System.Diagnostics.Debug.WriteLine("HasValue3 = {0}", d.HasValue); //False
The variable itself cannot be null, though you can set the minValue, it is an equivalent to '1/1/0001 00:00:00'
DateTime dvar = DateTime.MinValue;

Categories

Resources