Parsing value into nullable enumeration
Asked Answered
S

4

15

Let's say I have this:

PriorityType? priority;
string userInput = ...;

I cannot change how this is defined: PriorityType? priority because it's actually part of a contract with another piece of code.

I tried this, but it does not work:

if (Enum.TryParse<PriorityType?>(userInput, out priority)) {

What is the correct way?

Spooky answered 23/10, 2015 at 20:52 Comment(3)
You can't create a temporary PriorityType and then assign it to priority after you parse it?Plasticize
Yeah, I can, just thought there was maybe a better way. Post this as an answer and if there's not a better way, then I'll accept yours. :)Spooky
I don't think there is. The TEnum generic parameter is setup as where TEnum: struct.Agateware
P
9

The simplest way:

PriorityType tempPriority;
PriorityType? priority;

if (Enum.TryParse<PriorityType>(userInput, out tempPriority))
    priority = tempPriority;

This is the best I can come up with:

public static class NullableEnum
{
    public static bool TryParse<T>(string value, out T? result) where T :struct, IConvertible
    {
        if (!typeof(T).IsEnum)
            throw new Exception("This method is only for Enums");

        T tempResult = default(T);

        if (Enum.TryParse<T>(value, out tempResult))
        {
            result = tempResult;
            return true;
        }

        result = null;
        return false;
    }
}

Use:

if (NullableEnum.TryParse<PriorityType>(userInput, out priority))

The above class can be used just like Enum.TryParse except with a nullable input. You could add another overloaded function that takes a non-nullable T so that you could use it in both instances if you want. Unfortunately extension methods don't work very well on enum types (as far as I could try to manipulate it in the short time I tried).

Plasticize answered 23/10, 2015 at 21:6 Comment(0)
D
21

If you want it to be a single line of code, you can do it like this:

var priority = Enum.TryParse<PriorityType>(userInput, out var outPriority) ? outPriority : (PriorityType?) null;
Dacoity answered 10/12, 2019 at 9:39 Comment(0)
P
9

The simplest way:

PriorityType tempPriority;
PriorityType? priority;

if (Enum.TryParse<PriorityType>(userInput, out tempPriority))
    priority = tempPriority;

This is the best I can come up with:

public static class NullableEnum
{
    public static bool TryParse<T>(string value, out T? result) where T :struct, IConvertible
    {
        if (!typeof(T).IsEnum)
            throw new Exception("This method is only for Enums");

        T tempResult = default(T);

        if (Enum.TryParse<T>(value, out tempResult))
        {
            result = tempResult;
            return true;
        }

        result = null;
        return false;
    }
}

Use:

if (NullableEnum.TryParse<PriorityType>(userInput, out priority))

The above class can be used just like Enum.TryParse except with a nullable input. You could add another overloaded function that takes a non-nullable T so that you could use it in both instances if you want. Unfortunately extension methods don't work very well on enum types (as far as I could try to manipulate it in the short time I tried).

Plasticize answered 23/10, 2015 at 21:6 Comment(0)
P
4

This is the same solution posted by Ron Beyer with a little refactoring:

 public static class NullableEnum
{
    public static bool TryParse<T>(string value, out T? result) where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("Invalid Enum");

        result = Enum.TryParse(value, out T tempResult) ? tempResult : default(T?);

        return (result == null) ? false : true;
    }
}
Pilot answered 16/6, 2018 at 21:5 Comment(1)
Works nicely but I'm wondering why it doesn't work if you just use default (vs default(T?)).Firebrat
D
0

Another approach here that actually lets you handle the nullable enums rather than failing when you get them:

public static class EnumHelper {

    public static TEnum Parse<TEnum>( string value ){
        if( typeof(TEnum).IsEnum )
            return (TEnum)Enum.Parse( typeof(TEnum), value );

        Type? nullableType = Nullable.GetUnderlyingType( typeof(TEnum) );
        if( /*not a nullable type*/nullableType is null )
            throw new ArgumentException( $"Provided type {typeof(TEnum).Name} must be either an enum or a nullable enum" );

        return (TEnum?)Enum.Parse( nullableType, value );
    }

}

Call pattern is slightly different than the base lib that uses the out param, but can wrap it in the same call pattern if you like. Above for most cases tends to be easier to work with.

Dollie answered 28/5, 2021 at 14:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.