Skip to content

Common Type Constraints for OneOf Members #206

@BrunoJuchli

Description

@BrunoJuchli

A situation that I find myself in repeatedly is that I have a OneOf n-types which share some characteristics. They are not the same but they are similar enough.

So I find myself using OneOfBase like:
In some cases I resolve this by using a base class instead of a OneOf to represent the DU. Something like

abstract class Animal
{
     public string Name { get; set; }

     public abstract T Match<T>(
         Func<Racoon, T> racoon,
         Func<Fox, T> fox);
}

class Racoon : Animal
{
     public T Match<T>(
         Func<Racoon, T> racoon,
         Func<Fox, T> fox);
     {
         return racoon(this);
     }
}

class Fox : Animal
{
     public T Match<T>(
         Func<Racoon, T> racoon,
         Func<Fox, T> fox);
     {
         return fox(this);
     }
}

However, if other base classes are involved, or the types are not related enough for other reasons, this is not an option.

When using a oneof, I'd write it as:

public class Animal : OneOfBase<Racoon, Fox>
{
    public string Name => Match(
        x => x.Name,
        x => x.Name);
}

Of course it can get significantly more involved with multiple properties / methods. It's not efficient in terms of coding and performance.

So I was thinking we could do something like:

static class AllAre<T>
{
      abstract class OneOfBase<T1,T2,T3>
      where T1 : T
      where T2 : T
      where T3 : T
      {
           T Value { get; } // instead of object. The rest would be the usual OneOf stuff.
      }
}

class Animal: AllAre<IAnimal>.OneOf<
     Racoon,
     Fox>
{
    public string Name => Value.Name;
}

Have you ever considered this? Do you see a reason against it?
Of course it could get more complicated, like wanting to have more type constraints like AllAre<IAnimal, IDisposable>.

Specifically I'm asking here not just for "should it be integrated into the OneOf library" but more on a conceptual level. After all, if it isn't integrated into OneOf, it could also be done in a separate library.

Thank you

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions