Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attribute decoration to generate cast from one OneOfBase to another #132

Open
BreadTh opened this issue Nov 18, 2022 · 1 comment
Open

Comments

@BreadTh
Copy link

BreadTh commented Nov 18, 2022

Considder the following code:

public class Scenario
{
    private readonly Random random = new();

    public RealOutcome DoSomething()
    {
        if (random.Next() > int.MaxValue / 2)
            return new ErrorA();

        //Error: Cannot implicitly convert 'PartialOutcome' to 'RealOutcome'
        return DoSomethingElse();
    }

    private PartialOutcome DoSomethingElse()
    {
        if (random.Next() > int.MaxValue / 2)
            return new ErrorB();

        if (random.Next() > int.MaxValue / 2)
            return new ErrorC();

        return new TheResult();
    }
}


[GenerateOneOf]
public partial class RealOutcome : OneOfBase<
    TheResult,
    ErrorA,
    ErrorB,
    ErrorC>
{ }

[GenerateOneOf]
public partial class PartialOutcome : OneOfBase<
    TheResult,
    ErrorB,
    ErrorC>
{ }

public class TheResult { }
public class ErrorA { }
public class ErrorB { }
public class ErrorC { }

To remedy the error, one can add to RealOutcome the following boilerplate method:

public static implicit operator RealOutcome(PartialOutcome other)
{
    if (other.TryPickT0(out TheResult pick0, out OneOf<ErrorB, ErrorC> rest0))
        return pick0;
    if (rest0.TryPickT0(out ErrorB pick1, out var pick2))
        return pick1;
    return pick2;
}

I've done this more than a few times now (love this library!), so it would be really nice to have a shorthand that just generates the cast. Something like [GenerateOneOfImplicitCastAttribute<PartialOutcome>] (Now that we have generic attributes!)

This should of course only work if the type cast from's generic types are all contained in the cast to's generic types

I'd write it myself, but source generators still bend my mind for the time being.

@GuyWhoKnowsTheGuy
Copy link

This is particularly useful when when using option types, for example

[GenerateOneOf]
public partial class StringOrNumber : OneOfBase<string, int> { }

StringOrNumber myString = "My String"; // this compiles
StringOrNumber myNumber = 2; // this compiles

OneOf<StringOrNumber, None> foo = 3; // this does NOT compile
OneOf<StringOrNumber, None> bar = "hello world"; // this does NOT compile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants