-2

I am looking to check the value of an enum set in a generic class. When I try to write a basic if statement if (item.Value == AlphaType.A1), I got the following error:

Operator '==' cannot be applied to operands of type 'T' and 'Program.AlphaType'

Here is the code:

public enum AlphaType
{
    A1,
    A2
}

public enum BetaType
{
    B1,
    B2
}

public class Item<T>
{
    public T Value { get; set; }
    public string Foo { get; set;}
}

public static void Main()
{
    var item1 = new Item<AlphaType> { Value =  AlphaType.A1, Foo = "example 1" };
    var item2 = new Item<BetaType> { Value =  BetaType.B1, Foo = "example 2" };

    PrintAlphaFoo(item1);
    PrintAlphaFoo(item2);
}

public static void PrintAlphaFoo<T>(Item<T> item)
{
    if (item.Value == AlphaType.A1)
    {
        Console.WriteLine(item.Foo);
    }
}

Try it online!

Here the code should output example 1 but not example 2.

aloisdg
  • 22,270
  • 6
  • 85
  • 105
  • Possible duplicate of [Value of type 'T' cannot be converted to](https://stackoverflow.com/questions/4092393/value-of-type-t-cannot-be-converted-to) – Sinatr Feb 05 '19 at 14:05

2 Answers2

2

The operator cannot be used because you have a type mismatch. The compile cannot know that T is your enum. You can fix it by casting your value to an object then by casting again to your type:

if ((AlphaType)(object)item.Value == AlphaType.A1)

or we can even let Equals to the cast for us and write:

if (item.Value.Equals(AlphaType.A1))

But you cant stop here. Your error is fixed but not your main problem. With only this, example 2 is going to be print. You must do another check before:

if (item.Value.GetType() == typeof(AlphaType) && (AlphaType)(object)item.Value == AlphaType.A1)

Full code:

public enum AlphaType
{
    A1,
    A2
}

public enum BetaType
{
    B1,
    B2
}

public class Item<T>
{
    public T Value { get; set; }
    public string Foo { get; set;}
}

public static void Main()
{
    var item1 = new Item<AlphaType> { Value =  AlphaType.A1, Foo = "example 1" };
    var item2 = new Item<BetaType> { Value =  BetaType.B1, Foo = "example 2" };

    PrintAlphaFoo(item1);
    PrintAlphaFoo(item2);
}

public static void PrintAlphaFoo<T>(Item<T> item)
{
    if (item.Value.GetType() == typeof(AlphaType) && item.Value.Equals(AlphaType.A1))
    {
        Console.WriteLine(item.Foo);
    }
}

Try it Online

Source:

aloisdg
  • 22,270
  • 6
  • 85
  • 105
  • Note: boxing for this is expensive; it would be preferable to use `EqualityComparer.Default.Equals` if it works (I suspect it will); note that `.GetType()` is a boxing operation, too – Marc Gravell Feb 05 '19 at 14:02
  • I don't understand why you would ever have this code in the first place. If `T` is going to always be `AlphaType` then the signature of the `PrintAlphaFoo` method should reflect that - i.e. `PrintAlphaFoo(Item item)` – DavidG Feb 05 '19 at 14:14
  • @DavidG this is a basic [MCVE]. PrintAlphaFoo is a copycat of a method call in several part of the application. I have to check for different type also. – aloisdg Feb 05 '19 at 14:18
  • 1
    Yes, but I'm saying it's a terrible method, not that your code is wrong (or I would have downvoted). The fact you are trying to compare `item.Value` to a specific type is suggestive of a nasty code smell. – DavidG Feb 05 '19 at 14:19
  • @aloisdg hmmm; yeah, there's an extra complication in this case... in hindsight it might not be conveniently possible, sorry for any confusion – Marc Gravell Feb 05 '19 at 14:34
  • @MarcGravell Even if it is not helpful here at the end, I still learned somthing. I never hear about `EqualityComparer.Default.Equals` before. – aloisdg Feb 05 '19 at 14:36
0

You can as well try Enum.TryParse() method like

    public static void PrintAlphaFoo<T>(Item<T> item)
    {
        AlphaType alphaType;
        if (!Enum.TryParse<AlphaType>(item.Value.ToString(), out alphaType))
        {
            return;
        }

        if (alphaType == AlphaType.A1)
        {
            Console.WriteLine(item.Foo);
        }
    }
Rahul
  • 76,197
  • 13
  • 71
  • 125
  • Both example 1 and example 2 will be print here. [demo](https://dotnetfiddle.net/V8omft). It can be fix with a guard clause [demo](https://dotnetfiddle.net/EfkDMP). Isnt the toString and the parse costly? – aloisdg Feb 05 '19 at 14:22
  • Um, if the `TryParse` fails, this will make the default value of `alphaType` always be `A1`, I guess you want to check for that? – DavidG Feb 05 '19 at 14:25
  • @DavidG yes got it ... that's a mistake indeed – Rahul Feb 05 '19 at 14:30