Skip to content

Match/Switch methods on members #154

Description

@jupjohn

Describe the feature

Mentioned as an alternative to the implemented solution under #125, I believe that Dunet-like Match/Switch methods would be a good addition as, opposed to C#'s switch expression/statements on the underlying value, it allows for compile-time guarantees that all members are explicitly handled.

I don't believe it's necessary to have the "this-member-or-else" matching that a library like Dunet has (i.e. MatchMyMember(Func<Union.MyMember, T> matched, Func<T> @else) as expecting specific members can still be done with simple x == MyEnum.MyMemberValue checks. Perhaps having the ability to pass in a state object to reduce/prevent closure allocations would be nice (see Dunet's stateful matching.)

Rough idea of how I see this looking (for Match)

[Intellenum<int>]
[Member("Motorbike", 1)]
[Member("ATV", 2)]
[Member("Reliant Robin", 3)]
public partial class VehicleType;

// Source-gen stubs
public TReturn Match<TReturn>(
    Func<VehicleType, TReturn> matchMotorbike,
    Func<VehicleType, TReturn> matchAtv,
    Func<VehicleType, TReturn> matchReliantRobin
);

public void Switch(  // SwitchAsync would also be nice
    Action<VehicleType> matchMotorbike,
    Action<VehicleType> matchAtv,
    Action<VehicleType> matchReliantRobin
);

// Usage
var vehicleType = VehicleType.ReliantRobin;

var wheelCount = vehicleType.Match(
    motorbike => 2,
    atv => 4,
    reliantRobin => 3
);

// "Vehicle "Reliant Robin" has 3 wheels"
Console.WriteLine($"Vehicle \"{vehicleType.Name}\" has {wheelCount} wheels.")

Potential issues

An issue I can foresee with this (which is also an issue in Dunet, but less due to type safety) is when the order of the enum's members is changed, the Match method will still be correct from a compiler's perspective, but the matched function may be different unless you explicitly specified parameter names. Sounds like a nasty thing to encounter in the real world.

The only way I see to get around this is to go fully down the discriminated union path and give members distinct types OR only type them as parameters to Match/Switch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions