0

In the code below;

CustomClass<EnType1> a = new CustomClass<EnType1>();
CustomClass<TEnum<EnType1>> b = new CustomClass<TEnum<EnType1>>();

Throws error

The type ConsoleApp2.TEnum<ConsoleApp2.EnType1> cannot be used as type parameter T in the generic type or method CustomClass<T>. There is no implicit reference conversion from ConsoleApp2.TEnum<ConsoleApp2.EnType1> to System.Enum. and The type ConsoleApp2.EnType1 cannot be used as type parameter T in the generic type or method CustomClass<T>. There is no boxing conversion from ConsoleApp2.EnType1 to ConsoleApp2.IEnum.

How do I resolve this?

Basically I want to create a generic class which I should be able to use any Enum and then any class that inherits from IEnum

Any help appreciated

Full Code:

class Program
{
    static void Main(string[] args)
    {
        CustomClass<EnType1> a = new CustomClass<EnType1>();
        CustomClass<TEnum<EnType1>> b = new CustomClass<TEnum<EnType1>>();

        TEnum<EnType2> t = new TEnum<EnType2>(EnType2.B);
        Console.WriteLine("Hello World!" + t.EnumValue);
    }
}

In this generic class I should be able to use any Enum and then any class that inherits from IEnum

public class CustomClass<T> where T : Enum, IEnum
{
    public T Enum;
}

enum EnType1
{
    A = 2,
    B = 3
}

enum EnType2
{
    A = 0,
    B = 1
}

public interface IEnum
{
    public int EnumValue { get; set; }
}

public class TEnum<T> : IEnum
{
    public TEnum(T enumVal)
    {
        EnumValue = (int)(object)enumVal;
    }
    public int EnumValue { get ; set ; }
}
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • 1
    `Enum, IEnum` means that the T implements **both**, not just one of them. So, the constraints are combined with **AND** not with **OR**. – Peter Csala Jun 15 '21 at 13:39
  • Does this answer your question? [Generic method multiple (OR) type constraint](https://stackoverflow.com/questions/10833918/generic-method-multiple-or-type-constraint) – Peter Csala Jun 15 '21 at 13:41
  • Thanks.. but that doesn't solve my problem sadly.. The example above shows method which is a good alternative. But I need to have generic object as a property which cannot be achieve in similar way – digitally_inspired Jun 15 '21 at 13:47

1 Answers1

1

With the OneOf you can create a custom class, which represents either a built-in enum or a custom enum.

public class EitherEnum : OneOfBase<Enum, IEnum>
{
    public EitherEnum(OneOf<Enum, IEnum> _)
        : base(_) { }

    public bool IsStandard => IsT0;
    public Enum Standard => AsT0;

    public bool IsCustom => IsT1;
    public IEnum Custom => AsT1;
}

You can't use OneOf<T1,T2>, because it is a struct and that can't be used as generic constraint. The same applies Language-ext's Either type.

With this little class you can do the following:

public class CustomClass<T> where T : EitherEnum
{
    public T Enum;
}

CustomClass<EitherEnum> cc = new CustomClass<EitherEnum>();
cc.Enum = new EitherEnum(EnType1.A);
//OR
cc.Enum = new EitherEnum(new CustomEnum());

cc.Enum.Switch(
    standard => Console.WriteLine($"Standard: {standard}"),
    custom => Console.WriteLine($"Custom: {custom}"));
//OR
if(cc.Enum.IsStandard)
   Console.WriteLine($"Standard: {cc.Enum.Standard}")
else if (cc.Enum.IsCustom)
   Console.WriteLine($"Custom: {cc.Enum.Custom}")
Peter Csala
  • 17,736
  • 16
  • 35
  • 75