250 votes

Est-il un moyen de vérifier si l'int est légal enum en C#?

J'ai lu quelques SORTE postes et il semble que la plupart des opérations de base est manquant. PEUT-IL ÊTRE??

public enum LoggingLevel
{
    Off = 0,
    Error = 1,
    Warning = 2,
    Info = 3,
    Debug = 4,
    Trace = 5
};



if (s == "LogLevel")
{
    _log.LogLevel = (LoggingLevel)Convert.ToInt32("78");
    _log.LogLevel = (LoggingLevel)Enum.Parse(typeof(LoggingLevel), "78");
    _log.WriteDebug(_log.LogLevel.ToString());
}

pas d'exceptions. 78 est heureusement écrit. c'est triste. J'ai lu pourquoi le casting n'est pas automatiquement lancer l'erreur, mais s'il vous PLAÎT!!! AUCUN moyen de le vérifier à tous. C'est juste trop...

Merci et BR -Matti

410voto

SwDevMan81 Points 22634

Découvrez Enum.IsDefined
C'est l'exemple de cette page:

using System;

[Flags] public enum PetType
{
   None = 0, Dog = 1, Cat = 2, Rodent = 4, Bird = 8, Reptile = 16, Other = 32
};

public class Example
{
   public static void Main()
   {
      object value; 

      // Call IsDefined with underlying integral value of member.
      value = 1;
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      // Call IsDefined with invalid underlying integral value.
      value = 64;
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      // Call IsDefined with string containing member name.
      value = "Rodent";
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      // Call IsDefined with a variable of type PetType.
      value = PetType.Dog;
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      value = PetType.Dog | PetType.Cat;
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      // Call IsDefined with uppercase member name.      
      value = "None";
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      value = "NONE";
      Console.WriteLine("{0}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      // Call IsDefined with combined value
      value = PetType.Dog | PetType.Bird;
      Console.WriteLine("{0:D}: {1}", value, Enum.IsDefined(typeof(PetType), value));
      value = value.ToString();
      Console.WriteLine("{0:D}: {1}", value, Enum.IsDefined(typeof(PetType), value));
   }
}
// The example displays the following output:
//       1: True
//       64: False
//       Rodent: True
//       Dog: True
//       Dog, Cat: False
//       None: True
//       NONE: False
//       9: False
//       Dog, Bird: False

36voto

joshcomley Points 9308

Les solutions ci-dessus ne traitent pas de l' [Flags] des situations.

Ma solution ci-dessous peuvent avoir certains problèmes de performances (je suis sûr que l'on pourrait optimiser de diverses façons), mais essentiellement, il sera toujours prouver si une valeur d'enum est valide ou pas.

Il s'appuie sur deux choses:

  • Les valeurs de l'Enum en C# ne sont autorisés à être int, absolument rien d'autre
  • Enum noms en C# doit commencer par un caractère alphabétique

Appelant ToString() sur un enum renvoie l' int de la valeur si aucun protocole enum (drapeau ou pas) est mis en correspondance. Si un permis de valeur d'enum est adapté, il permet d'imprimer le nom du match(es).

Donc:

[Flags]
enum WithFlags
{
    First = 1,
    Second = 2,
    Third = 4,
    Fourth = 8
}

((WithFlags)2).ToString() ==> "Second"
((WithFlags)(2 + 4)).ToString() ==> "Second, Third"
((WithFlags)20).ToString() ==> "20"

Ces deux règles en tête, nous pouvons supposer que si l' .NET Framework fait son travail correctement que tous les appels à un valide l'enum ToString() méthode se traduira par quelque chose qui a un caractère alphabétique comme premier caractère:

public static bool IsValid<TEnum>(this TEnum enumValue)
    where TEnum : struct
{
    var firstChar = enumValue.ToString()[0];
    return firstChar < '0' || firstChar > '9';
}

On pourrait parler d'un "hack", mais les avantages sont qu'en s'appuyant sur de Microsoft de la mise en œuvre de l' Enum et C#, vous n'êtes pas en s'appuyant sur votre propre potentiellement code bogué ou de vérifications. Dans les situations où la performance n'est pas exceptionnellement critique, cela permettra d'économiser beaucoup de méchant switch des déclarations ou d'autres vérifications!

Et les tests pour les sauvegarder:

[TestClass]
public class EnumExtensionsTests
{
    [Flags]
    enum WithFlags
    {
        First = 1,
        Second = 2,
        Third = 4,
        Fourth = 8
    }

    enum WithoutFlags
    {
        First = 1,
        Second = 22,
        Third = 55,
        Fourth = 13,
        Fifth = 127
    }

    enum WithoutNumbers
    {
        First, // 1
        Second, // 2
        Third, // 3
        Fourth // 4
    }

    enum WithoutFirstNumberAssigned
    {
        First = 7,
        Second, // 8
        Third, // 9
        Fourth // 10
    }

    [TestMethod]
    public void IsValidEnumTests()
    {
        Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
        Assert.IsTrue(((WithFlags)(1 | 4)).IsValid());
        Assert.IsTrue(((WithFlags)(1 | 4 | 2)).IsValid());
        Assert.IsTrue(((WithFlags)(2)).IsValid());
        Assert.IsTrue(((WithFlags)(3)).IsValid());
        Assert.IsTrue(((WithFlags)(1 + 2 + 4 + 8)).IsValid());

        Assert.IsFalse(((WithFlags)(16)).IsValid());
        Assert.IsFalse(((WithFlags)(17)).IsValid());
        Assert.IsFalse(((WithFlags)(18)).IsValid());
        Assert.IsFalse(((WithFlags)(0)).IsValid());

        Assert.IsTrue(((WithoutFlags)1).IsValid());
        Assert.IsTrue(((WithoutFlags)22).IsValid());
        Assert.IsTrue(((WithoutFlags)(53 | 6)).IsValid()); // Will end up being Third
        Assert.IsTrue(((WithoutFlags)(22 | 25 | 99)).IsValid()); // Will end up being Fifth
        Assert.IsTrue(((WithoutFlags)55).IsValid());
        Assert.IsTrue(((WithoutFlags)127).IsValid());

        Assert.IsFalse(((WithoutFlags)48).IsValid());
        Assert.IsFalse(((WithoutFlags)50).IsValid());
        Assert.IsFalse(((WithoutFlags)(1 | 22)).IsValid());
        Assert.IsFalse(((WithoutFlags)(9 | 27 | 4)).IsValid());

        Assert.IsTrue(((WithoutNumbers)0).IsValid());
        Assert.IsTrue(((WithoutNumbers)1).IsValid());
        Assert.IsTrue(((WithoutNumbers)2).IsValid());
        Assert.IsTrue(((WithoutNumbers)3).IsValid());
        Assert.IsTrue(((WithoutNumbers)(1 | 2)).IsValid()); // Will end up being Third
        Assert.IsTrue(((WithoutNumbers)(1 + 2)).IsValid()); // Will end up being Third

        Assert.IsFalse(((WithoutNumbers)4).IsValid());
        Assert.IsFalse(((WithoutNumbers)5).IsValid());
        Assert.IsFalse(((WithoutNumbers)25).IsValid());
        Assert.IsFalse(((WithoutNumbers)(1 + 2 + 3)).IsValid());

        Assert.IsTrue(((WithoutFirstNumberAssigned)7).IsValid());
        Assert.IsTrue(((WithoutFirstNumberAssigned)8).IsValid());
        Assert.IsTrue(((WithoutFirstNumberAssigned)9).IsValid());
        Assert.IsTrue(((WithoutFirstNumberAssigned)10).IsValid());

        Assert.IsFalse(((WithoutFirstNumberAssigned)11).IsValid());
        Assert.IsFalse(((WithoutFirstNumberAssigned)6).IsValid());
        Assert.IsFalse(((WithoutFirstNumberAssigned)(7 | 9)).IsValid());
        Assert.IsFalse(((WithoutFirstNumberAssigned)(8 + 10)).IsValid());
    }
}

16voto

Marc Gravell Points 482669

La réponse canonique serait Enum.IsDefined, mais c'est un: un peu lent, si elle est utilisée dans une boucle serrée, et b: pas utile pour [Flags] des enums.

Personnellement, j'avais cesser de s'inquiéter à ce sujet, et juste switch correctement, se souvenir de:

  • si c'est OK de ne pas reconnaître tout (et juste ne rien faire), alors il ne faut pas ajouter un default: (ou vide default: expliquant pourquoi)
  • si il y a un bon comportement par défaut, placez-le dans l' default:
  • sinon, poignée de ceux qui vous connaissent et qui lève une exception pour le reste:

Comme suit:

switch(someflag) {
    case TriBool.Yes:
        DoSomething();
        break;
    case TriBool.No:
        DoSomethingElse();
        break;
    case TriBool.FileNotFound:
        DoSomethingOther();
        break;
    default:
        throw new ArgumentOutOfRangeException("someflag");
}

15voto

n535 Points 2558

Utilisation:

Enum.IsDefined ( typeof ( Enum ), EnumValue );

7voto

driis Points 70872

L'Utilisation D'Enum.IsDefined.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X