Comment utiliser le Tryparse générique avec Enum?

j'essaie de construire une fonction générique qui obtient à partir de la chaîne de caractères de l'utilisateur et d'essayer de la Parser à Enum valuse comme ceci:

private Enum getEnumStringEnumType(Type i_EnumType)
    {
        string userInputString = string.Empty;
        Enum resultInputType;
        bool enumParseResult = false;

        while (!enumParseResult)
        {                
            userInputString = System.Console.ReadLine();
            enumParseResult = Enum.TryParse(userInputString, true, out resultInputType);
        }
    }

Mais j'obtiens:

The type 'System.Enum' must be a non-nullable value type in order to use it as parameter 'TEnum' in the generic type or method 'System.Enum.TryParse<TEnum>(string, bool, out TEnum)    .

L'erreur signifie que je dois décaler un Enum spécifique pour resultInputType? Comment je peux arranger ça ? Grâce.

24
demandé sur abatishchev 2012-05-21 17:04:17

4 réponses

TryParse méthode porte la signature suivante:

TryParse<TEnum>(string value, bool ignoreCase, out TEnum result)
    where TEnum : struct

il a un paramètre de type générique TEnum ça doit être une struct et qui sert à déterminer le type d'énumération à analyser. Quand vous ne le fournissez pas explicitement( comme vous l'avez fait), il prendra le type de ce que vous fournissez comme result argument, qui dans votre cas est de type Enum (et non le type de l'énumération elle-même).

Notez que Enum est un classe (malgré qu'il hérite de ValueType) et ne satisfait donc pas à l'exigence que TEnum est un struct.

vous pouvez résoudre cela en supprimant le Type paramètre et donnant à la méthode un paramètre de type générique avec les mêmes contraintes (i.e. struct) comme paramètre de type générique sur le TryParse fonction.

alors essayez ceci, où j'ai nommé le paramètre de type générique TEnum:

private static TEnum GetEnumStringEnumType<TEnum>()
    where TEnum : struct
{
    string userInputString = string.Empty;
    TEnum resultInputType = default(TEnum);
    bool enumParseResult = false;

    while (!enumParseResult)
    {                
        userInputString = System.Console.ReadLine();
        enumParseResult = Enum.TryParse(userInputString, true, out resultInputType);
    }
    return resultInputType;
}

Pour appeler la méthode, utilisez:

GetEnumStringEnumType<MyEnum>();
44
répondu Daniel Pelsmaeker 2017-01-26 10:15:31

vous devez faire une méthode générique:

private T getEnumStringEnumType<T>() where T : struct, IConvertible
    {
        string userInputString = string.Empty;
        T resultInputType = default(T);
        bool enumParseResult = false;

        while (!enumParseResult)
        {
            userInputString = System.Console.ReadLine();
            enumParseResult = Enum.TryParse<T>(userInputString, out resultInputType);
        }

        return resultInputType;
    }

utilisation:

public enum myEnum { val1, val2 }

myEnum enumValue = getEnumStringEnumType<myEnum>();
4
répondu eyossi 2012-05-21 14:37:29

Enum.TryParse est une méthode générique, ce qui signifie que ses paramètres de type générique doivent être connus au moment de la compilation. Cela signifie que, oui, vous avez à déclarer resultInputTypecertains taper enum pour le code à compiler.

si vous y pensez, le code original est un peu trop optimiste: il ne dit nulle part le type enum doit être vérifié pour un membre dont le nom est userInputString. Comment pourrait -TryParse travailler sans cette information?

1
répondu Jon 2012-05-21 13:07:24

Il y a longtemps dans L'ère Visual Studio 2005, j'ai fait ma propre méthode pour TryParse sur Enum. Je n'ai découvert que récemment la mise en œuvre 2008 et je ne suis pas satisfait de son caractère restrictif, surtout si on considère qu'il s'agit d'un TRY PARSE méthode; ce qui signifie qu'un programmeur teste une entrée!

en Général, je préfère utiliser des méthodes confiance au programmeur de savoir ce qu'il fait :)

Mon application est comme suit:

public static bool EnumTryParse<T>(string input, out T theEnum)
{
    foreach (string en in Enum.GetNames(typeof(T)))
    {
        if (en.Equals(input, StringComparison.CurrentCultureIgnoreCase))
        {
            theEnum = (T)Enum.Parse(typeof(T), input, true);
            return true;
        }
    }

    theEnum = default(T);
    return false;
}

L'absence d'un où T: struct place la confiance dans les mains du développeur, mais il vous permet de compiler avec des énums génériques inconnus.

comme alternative, vous pouvez créer une boucle de méthode sur Enum.GetValues si vous voulez faire une comparaison entière lors de la conversion à votre enum spécifié.

Espérons que cette aide.

1
répondu Mark Mintoff 2012-07-17 11:46:55