How to deconstruction Nullable Tuple?
Asked Answered
G

2

11

I am using C# 8.0 with NullableContextOptions (Nullable Reference) enabled.

I have a function with this signature:

public static (int line, string content)? GetNextNonEmptyLineDown(this IList<string> contents, int fromLine)

Basically, it returns the line and the content if there is non-empty line down, and returns if there is none.

The problem is I don't know how to deconstruct it. If I try:

var (firstLineIndex, firstLine) = content.GetNextNonEmptyLineDown(0);

I receive the 4 syntax errors:

enter image description here

So I can only use:

        var lineInfo = content.GetNextNonEmptyLineDown(0);

        var firstLineIndex =  lineInfo.Value.line;
        var firstLine = lineInfo.Value.content;

which destroys the purpose. lineInfo is of type struct<T> where T is (int line, string content)

Is there anyway to deconstruct a nullable tuple?

EDIT: after posting the question, it comes to my mind that it makes no sense to allow deconstructing of nullable tuple as the data type of the variables may not be determined. Here is my current fix but wonder if this is the best way:

        var lineInfo = content.GetNextNonEmptyLineDown(0);

        if (lineInfo == null)
        {
            throw new Exception();
        } 

        var (firstLineIndex, firstLine) = lineInfo.Value;
Gerek answered 2/3, 2019 at 18:23 Comment(2)
What do you want to do if content.GetNextNonEmptyLineDown(0); is null? If you want to swop nulls out for defaults, you can domething like: var lineInfo = content.GetNextNonEmptyLineDown(0) ?? (0, ""); However, that's bad style. So your suggestion is probably best.Phosphatize
this has nothing to do with c# 8 or reference types. these are value tuples.Mutualism
S
21

From this question on nullable types:

Any Nullable is implicitly convertible to its T, PROVIDED that the entire expression being evaluated can never result in a null assignment to a ValueType.

So what you're looking for is to place at the right of the deconstruction a surely not-null expression. An elegant way to do this is:

var (firstLineIndex, firstLine) = lineinfo ?? default;

?? is the null-coalescing operator: it returns the value at its left if it is not null, the one at its right otherwise. What we place at the right is the default operator, which nicely fits its return type to the surrounding expression.

Note that the use of default is mainly to please the compiler, you may not want that value to be actually used at runtime. You should still check for null beforehand.

Stoup answered 2/10, 2019 at 17:49 Comment(0)
A
2

If you want to deconstruct nullable tuple of value types into Nullable this works(DateTime example):

(DateTime start, DateTime end)? foo = null;
(DateTime? start, DateTime? end) = foo ?? ((DateTime?)null, (DateTime?)null);

Ugly as sin, but works... Could be prettied up with extension methods, but you'd pretty much need one for each arity of ValueTuple.

Adulate answered 24/3, 2022 at 19:11 Comment(1)
"Could be prettied up with extension methods" - unfortunately doing that won't preserve tuple member names, as they cannot be preserved if the return-type does not exactly match the typeof the valuetuple. *grumble*Whipsaw

© 2022 - 2024 — McMap. All rights reserved.