2009-11-29 26 views
5

Ich habe eine generische Klasse und möchte erzwingen, dass Instanzen des Typparameters immer "cast-fähig"/konvertierbar von String sind. Ist es möglich ohne eine Schnittstelle zu verwenden?Wie überprüft man, ob eine implizite oder explizite Umwandlung existiert?

Mögliche Umsetzung:

public class MyClass<T> where T : IConvertibleFrom<string>, new() 
{ 
    public T DoSomethingWith(string s) 
    { 
     // ... 
    } 
} 

Ideal Umsetzung:

public class MyClass<T> 
{ 
    public T DoSomethingWith(string s) 
    { 
     // CanBeConvertedFrom would return true if explicit or implicit cast exists 
     if(!typeof(T).CanBeConvertedFrom(typeof(String)) 
     { 
      throw new Exception(); 
     } 
     // ... 
    } 
} 

Der Grund, warum ich diese "idealen" Implementierung vorziehen würde, ist in erster Linie, um alle Ts nicht zu zwingen, zu implementieren IConvertibleFrom <> .

+2

Was ist ideal an einer Implementierung, die auf Programmierzeitfehler mit Laufzeitausnahmen reagiert? –

+1

Wenn Sie eine Reihe von Typen haben, die bereits eine Zeichenfolge konvertieren, und Sie diese in einer neuen Klasse/Methode verwenden möchten, wie ich es abstrakt beschrieben habe, wäre dies die Methode mit dem geringsten Aufwand, sie zu implementieren. Es wäre eine Farbe, jeden Typ zu bearbeiten und die neue Schnittstelle zu implementieren. –

Antwort

3

Vorausgesetzt, dass Sie aus dem abgedichteten Typ String konvertieren möchten, können Sie mögliche nullable, Boxen, Referenz- und explizite ignorieren Konvertierungen. Nur op_Implicit() qualifiziert. Ein generischer Ansatz wird durch die System.Linq.Expressions.Expression-Klasse:

using System.Linq.Expressions; 
... 
    public static T DoSomethingWith(string s) 
    { 
     var expr = Expression.Constant(s); 
     var convert = Expression.Convert(expr, typeof(T)); 
     return (T)convert.Method.Invoke(null, new object[] { s }); 
    } 

Passen Sie die Kosten für die Reflexion.

+0

Das funktioniert, danke! –

-1

Warum können Sie so etwas nicht tun?

public class MyClass<T> where T : string 
{ 
    public T DoSomethingWith(string s) 
    { 
     // ... 
    } 
} 

Auf diese Weise können Sie überprüfen, ob s-T im DoSomethingWith Code umwandelbar ist. Von dort können Sie Ausnahme auslösen, wenn es nicht kann, oder das Gießen tun, wenn es kann

+1

Warum Generika überhaupt verwenden, wenn Sie explizit deklarieren, dass der generische Typ eine Zeichenkette sein muss? –

+0

d, ich erklärte 'T' als muss von String abgeleitet werden, das ist nicht das Gleiche wie sagen, es muss String sein. – Graviton

+1

Nein, ich habe meine eigenen Typen, die aus einer Zeichenfolge konvertiert werden können. (PS: Sie können nicht von String erben). –

-1
if(!typeof(T).IsAssignableFrom(typeof(String))) { 
    throw new Exception(); 
} 
+1

Funktioniert leider nicht mit impliziten oder expliziten Cast-Operatoren, die für den Argumenttyp deklariert sind. –

+0

hmm, ich bin mir nicht sicher, ob ich dir in deiner Antwort folge. Dieses Stück Code würde eine Ausnahme auslösen, wenn 'T' zum Beispiel ein int wäre, aber nicht, wenn es eine Zeichenfolge oder ein Objekt wäre. Ist das nicht das wonach du suchst? –

+0

Ich habe es mit der Klasse MyClass getestet {public static impliziter Operator MyClass (String s) {return new MyClass(); }} und typeof (MyClass) .IsAssignableFrom (typeof (string)) gibt false zurück. Ich nehme an, du hast erwartet, dass es wieder wahr wird ... –

Verwandte Themen