web-dev-qa-db-fra.com

C # Casting avec des objets à Enums

Cette question concerne le casting d'énums au sein de méthodes génériques

Donné un enum

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

Je peux créer assez simplement une instance de mon enum

short val = 4;
Crustaceans crusty = (Crustaceans) val;

Toutefois, si

short val = 4;
object obj = (object) val;
Crustaceans crusty = (Crustaceans)obj;

une exception d'exécution est levée alors qu'elle tente d'exécuter l'initialisation de Crusty.

Quelqu'un peut-il expliquer pourquoi cela se produit et pourquoi ce n'est pas légal de faire une telle chose.

Non pas que je veuille vraiment faire cela, mais je me suis heurté à un problème lorsque j'essayais de faire quelque chose de similaire avec les génériques et que c’est effectivement ce qui se passe sous la couverture. c'est à dire.

public T dosomething<T>(short val) where T : new()
{
    T result = (T)(object) val;
    return result;
}

Donc, ce que je tente de faire est d’avoir une fonction générique qui fonctionne avec des énumérations et des non-énumérations (pas si critique mais qui serait Nice) qui peut être définie sur une valeur courte sans lever d’exception ni initialiser la valeur d’énum correcte.

20
sweetfa

Quelque chose comme ceci probablement vous aidera à: 

public T dosomething<T>(object o)
{
   T enumVal= (T)Enum.Parse(typeof(T), o.ToString());
   return enumVal;
}

Mais cela fonctionnera seulement avec des enums, pour une raison claire d'utiliser Enum.Parse(..)

Et utilisez ceci comme, par exemple: 

object o = 4;
dosomething<Crustaceans>(o);

Cela renverra Toad dans votre cas.

36
Tigran

Il existe des cas où vous ne pouvez pas utiliser les génériques (comme dans un convertisseur WPF lorsque vous obtenez la valeur sous la forme object) . Dans ce cas, vous ne pouvez pas transtyper en int car le type enum peut ne pas être int. C'est une manière générale de le faire sans Génériques . L'exemple est donné à l'intérieur d'un convertisseur WPF, mais le code qu'il contient est général:

using System;
using System.Windows;
using System.Windows.Data;

.
.
.

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var enumType = value.GetType();
    var underlyingType = Enum.GetUnderlyingType(enumType);
    var numericValue = System.Convert.ChangeType(value, underlyingType);
    return numericValue;
}
3
Tal Segal

Dans le cas des types intégraux encadrés en tant qu'objets, la méthode correcte pour convertir est d'utiliser Enum.ToObject method:

public T Convert<T>(object o)
{
   T enumVal= (T)Enum.ToObject(typeof(T), o);
   return enumVal;
}
2
hazzik

Par défaut, les valeurs numériques enum ont le type = int. Dans votre code, vous souhaitez transtyper des valeurs de type court en type enum. Pour cela, vous devez définir le type court à vos valeurs enum. Cela fonctionnera:

public enum Crustaceans : short // <--
{
    Frog = 1,
    Toad = 4
}

short  @short = 1;
object @object = @short;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog   

si vous ne voulez pas changer le type de valeurs enum par défaut

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

object @object = Crustaceans.Frog;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog

ou

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

int @integer= 1;

var @enum = (Crustaceans)@integer; // @enum = Crustaceans.Frog
0