0

This sounds trivial but I am having challenge. I cannot convert a nullable to a non-nullable value:

if (caseObj.SyncDate != null)
    caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(caseObj.SyncDate);

Where my caseObj.SyncDate is defined as:

public DateTimeOffset? SyncDate {get;set;}

And my getFormattedDateTime is:

    public static string getFormattedDateTime(DateTimeOffset dateTimeOffset) {

        string returnDate = null;

        if (dateTimeOffset != null) {
            returnDate = dateTimeOffset.ToString("yyyy-MM-dd HH:mm:ss.fffzzz", CultureInfo.InvariantCulture);
        }
        return returnDate;
    }

I read this and tried:

        if (caseObj.SyncDate != null)
            caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(caseObj.SyncDate!):

Which seems strange since I saw this link to Microsoft documentation which states:

Sometimes you must override a warning when you know a variable isn't null, but the compiler determines its null-state is maybe-null. You use the null-forgiving operator ! following a variable name to force the null-state to be not-null. For example, if you know the name variable isn't null but the compiler issues a warning, you can write the following code to override the compiler's analysis:

But that didn't seem to work. I have read this post (which I thought was focused enough) and this one for which the marked solution was not to convert from nullable to null.

I have tried this as well:

        if (caseObj.SyncDate != null) {
            DateTimeOffset dto = (DateTimeOffset) caseObj.SyncDate;
            caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(dto);
        }

But get this:

Argument 1: cannot convert from 'System.DateTimeOffset?' to 'System.DateTime'

Which is strange because I am not trying to convert from System.DateTimeOffset? to System.DateTime. I am trying to convert System.DateTimeOffset? to DateTimeOffset.

I'm running dotnet core on a Mac (version 6.0.201). There seem to be some long complicated answers, but I assume there is a simple way to do this that I'm missing.

lcj
  • 1,355
  • 16
  • 37
  • Does this answer your question? [C#: passing nullable variable to method that only accepts nonnull vars](https://stackoverflow.com/questions/1705102/c-passing-nullable-variable-to-method-that-only-accepts-nonnull-vars) – GSerg Jun 20 '22 at 12:14
  • 1
    Check the error again. It says `cannot convert from 'System.DateTimeOffset?' to 'System.DateTime'`. That's two different types, DateTimeOffset and DateTime. The code you posted should fail for a different reason, trying to assing a string to a DateTimeOffset. This isn't the code that actually throws – Panagiotis Kanavos Jun 20 '22 at 12:15
  • To convert from `Nullable` to `T` you need to call the `Value` property. – juharr Jun 20 '22 at 12:17
  • @PanagiotisKanavos, the function is overloaded and can take a DateTime as well. I confirmed the DateTimeOffset is being passed in, or more accurately DateTimeOffset? is being passed in. Somehow it picked the DateTime vs the DateTimeOffset. – lcj Jun 20 '22 at 22:00
  • Post code that actually reproduces the error. And *strongly* consider changing the overloaded function name. Date types have no formats so `getFormattedDateTime` is the worst possible name for a function returning binary unformatted values – Panagiotis Kanavos Jun 21 '22 at 06:40
  • I will change the overloaded name and ensure I post all the code reproducing the error next time. That being said there might be worse names, like: iTypicallySpendTooLongPerseveratingAboutNamingMyFunctions(). – lcj Jun 21 '22 at 10:29

2 Answers2

4

If I get you right - you might want something like this:

if (caseObj.SyncDate.HasValue)
    caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(caseObj.SyncDate.Value);
Arthur Edgarov
  • 473
  • 5
  • 16
  • 1
    This worked too. Which I could select them both as the answer. – lcj Jun 20 '22 at 22:06
  • 1
    @lcj, Believe it or not, most of the community members are posting answers to share their knowledge and make developers' life easier, eventually making the entire world better, rather than just having those green checkmarks near the posted answer :) – Arthur Edgarov Jun 20 '22 at 22:13
  • I believe it. Developers are good people. I just wanted to show my appreciation. – lcj Jun 21 '22 at 10:25
1

By using pattern matching, you can write:

if (caseObj.SyncDate is { } syncDate) {
    caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(syncDate);
}

or

if (caseObj.SyncDate is DateTimeOffset syncDate) {
    caseDTO.SyncDate = DateTimeHelper.getFormattedDateTime(syncDate);
}

{ } is an empty property pattern which implicitly tests for not null. The result, a non-nullable DateTimeOffset is assigned to a new variable syncDate if the condition succeeds.

The second version uses a type pattern which tests whether the value is a DateTimeOffset. It only succeeds if the value is not null. null has no type and never satisfies a type test.

The nice thing about a pattern matching approach is that it does three things:

  1. it tests a condition
  2. it creates a local variable
  3. it casts the input value to the result type (DateTimeOffset? to DateTimeOffset in this case).
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188