2008-11-07 8 views
60

J'ai une classe qui stocke une valeur sérialisée et un type. Je veux avoir une propriété/méthode retournant la valeur déjà casted:Création d'une propriété générique

public String Value { get; set; } 

public Type TheType { get; set; } 

public typeof(TheType) CastedValue { get { return Convert.ChangeType(Value, typeof(_Type)); } 

Est-ce possible en C#?

+4

Les propriétés génériques seraient bien; Je pense que 'var val = obj.Prop ' est plus succinct pour une recherche basée sur le type que 'obj.Prop [typeof (Type)]' ou 'obj.GetProp ()'. – Dan

Répondre

93

Il est possible que si la classe contenant la propriété est générique, et vous déclarez la propriété à l'aide du paramètre générique:

class Foo<TValue> { 
    public string Value { get; set; } 
    public TValue TypedValue { 
     get { 
      return (TValue)Convert.ChangeType(Value, typeof(TValue)); 
     } 
    } 
} 

Une alternative serait d'utiliser une méthode générique à la place:

class Foo { 
    public string Value { get; set; } 
    public Type TheType { get; set; } 

    public T CastValue<T>() { 
     return (T)Convert.ChangeType(Value, typeof(T)); 
    } 
} 

Vous pouvez également utiliser les classes System.ComponentModel.TypeConverter pour convertir, car elles permettent à une classe de définir son propre convertisseur.

Modifier: Notez que lorsque vous appelez la méthode générique, vous devez spécifier le paramètre de type générique, car le compilateur n'a aucun moyen de le déduire:

Foo foo = new Foo(); 
foo.Value = "100"; 
foo.Type = typeof(int); 

int c = foo.CastValue<int>(); 

Vous devez connaître le type à la compilation . Si vous ne connaissez pas le type au moment de la compilation, vous devez être le stocker dans un object, auquel cas vous pouvez ajouter la propriété suivante à la classe Foo:

public object ConvertedValue { 
    get { 
     return Convert.ChangeType(Value, Type); 
    } 
} 
+0

Dans le second exemple de classe 'Foo, je suis déconcerté: une propriété publique' theType est déclaré: "public TypeType {get; set;}" mais ne semble pas être utilisé dans le code. merci, – BillW

+0

La propriété était dans l'exemple original. Je l'ai juste laissé. – Brannon

+0

Quand j'essaie la solution de Brannons, j'obtiens une erreur d'exécution disant que l'objet que je lance doit implémenter IConvertible. Ai-je fait quelque chose de mal parce que cela semble être un briseur d'affaires à moins de lancer un cours où j'ai la source disponible. – Keith

3

Je ne crois pas l'exemple que vous 'donné ici est possible. Le type de CastedValue doit être défini au moment de la compilation, ce qui signifie qu'il ne peut pas dépendre d'une valeur d'exécution (la valeur de la propriété TheType).

EDIT: La solution de Brannon a quelques bonnes idées pour gérer cela en utilisant une fonction générique plutôt qu'une propriété.

52

Les propriétés, les événements, les constructeurs, etc. ne peuvent pas être génériques - seules les méthodes et les types peuvent être génériques. La plupart du temps ce n'est pas un problème, mais je suis d'accord que c'est parfois douloureux. La réponse de Brannon donne deux solutions de contournement raisonnables.