ExhaustiveMatching icon indicating copy to clipboard operation
ExhaustiveMatching copied to clipboard

Support structurally closed hierarchies like Discriminated Unions based on C# records

Open csharper2010 opened this issue 2 years ago • 2 comments

Based on the work for #42 it would be nice to have the same feature also für discriminated unions implemented the C# record syntax.

public abstract record Result<TSuccess, TError> {
    private Result() { }

    public sealed record Success(TSuccess Value) : Result<TSuccess, TError>;

    public sealed record Error(TError value) : Result<TSuccess, TError>;
}

A switch with missing arms could also giving the analyzer error however there's a slight source of errors:

It is technically possible to subclass from the Result record outside of the scope because the C# record syntax for non-sealed records always creates a protected copy constructor. Anyway I would argue that the developer intention is clear as there are some intrinsics about what the copy constructor does and where it is used.

This line of code compiles even outside of the Result record but providing a concrete instance (Error in this case) does not make real sense as only the properties of the base record would be considered in the copy constructor:

public record OtherResult(string Value) : Result<string, string>(new Error(Value))

See also this StackOverflow question to see there are also other developers interested in such a feature.

As I understand it however, to really detect that situation, we must switch to Roslyn version 3.9.0 as the IsRecord property was added to the type symbol interface.

csharper2010 avatar Apr 05 '22 06:04 csharper2010

@csharper2010 This is great!

@WalkerCodeRanger I've tested this with our projects and it works well FWIW. We'd love to have this in, it would be super useful as we use this pattern pretty extensively.

jgilchrist avatar Apr 08 '22 11:04 jgilchrist

Very nice - look forward to giving this a try, thanks!

dcuccia avatar Apr 27 '22 14:04 dcuccia