2008-11-07 20 views
60

Ich habe eine Klasse, die einen serialisierten Wert und einen Typ speichert. Ich möchte eine Eigenschaft/Methode haben, die den bereits gegossenen Wert zurückgibt:Erstellen einer generischen Eigenschaft

Ist dies in C# möglich?

+4

Generische Eigenschaften wären nett; Ich denke, 'var val = obj.Prop ' ist prägnanter für eine typbasierte Suche als 'obj.Prop [typeof (Type)]' oder 'obj.GetProp ()'. – Dan

Antwort

93

Es ist möglich, wenn die Klasse die Eigenschaft ist generisch, und erklären Sie, die Eigenschaft mit dem generischen Parameter enthält:

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

Eine Alternative wäre, zu verwenden, um eine generische Methode statt:

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

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

Sie können auch die Klassen System.ComponentModel.TypeConverter zum Konvertieren verwenden, da sie einer Klasse erlauben, ihren eigenen Konverter zu definieren.

bearbeiten: beachten Sie, dass, wenn die generische Methode aufrufen, können Sie die generischen Typparameter angeben müssen, da der Compiler keine Möglichkeit, es zu schließen, hat:

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

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

Sie die Art zum Zeitpunkt der Kompilierung wissen müssen . Wenn Sie nicht die Art zum Zeitpunkt der Kompilierung wissen, dann müssen Sie es in diesem Fall in einem object, Speichern, Sie die folgende Eigenschaft auf die Foo Klasse kann hinzufügen:

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

Im zweiten Beispiel der Klasse 'Foo, bin ich verblüfft: eine öffentliche Eigenschaft' theType wird deklariert: "public Typ TheType {Get; Set;}" aber scheint nicht im Code verwendet werden. Danke, – BillW

+0

Das Anwesen war im ursprünglichen Beispiel. Ich habe es einfach gelassen. – Brannon

+0

Wenn ich Brannons Lösung versuche, bekomme ich einen Laufzeitfehler, der besagt, dass das Objekt, das ich werfe, IConvertible implementieren muss. Habe ich etwas falsch gemacht, weil dies wie ein Deal-Breaker aussieht, es sei denn, ich werfe eine Klasse aus, in der ich die Quelle verfügbar habe. – Keith

3

Ich glaube nicht, das Beispiel, das Sie hier gegeben ist möglich. Der Typ von CastedValue muss zur Kompilierzeit definiert werden, was bedeutet, dass er nicht von einem Laufzeitwert (dem Wert der TheType-Eigenschaft) abhängen kann.

EDIT: Brannon Lösung hat einige gute Ideen für den Umgang mit diesem mit einer generischen Funktion anstelle einer Eigenschaft.

52

Eigenschaften, Ereignisse, Konstruktoren usw. können nicht generisch sein - nur Methoden und Typen können generisch sein. Die meiste Zeit ist das kein Problem, aber ich stimme zu, dass es manchmal ein Schmerz ist. Brannons Antwort gibt zwei vernünftige Lösungen.

Verwandte Themen