2010-11-29 3 views
4

J'ai une fonction d'aide pour obtenir des valeurs de XML qui fonctionne bien avec des types de valeur comme ints et aussi des chaînes. J'ai aussi quelques classes qui prennent un XPathNavigator comme paramètre dans leurs constructeurs et je voudrais faire quelque chose comme ce qui suit:Fonction générique qui peut renvoyer des objets de type valeur et référence

public static void SelectSingleNodeSafe<T>(XPathNavigator nav, string pos, out T ret, T def) 
    { 
     XPathNavigator node = nav.SelectSingleNode(pos); 
     if (node != null) 
      if (typeof(T).IsSubclassOf(XMLConstructible)) 
       ret = new T(node);// this won't compile 
      else 
       ret = (T)node.ValueAs(typeof(T));//this works for my use cases 
     else 
      ret = def; 
    } 

Il y a une volonté, mais est-il un moyen?

+3

Les chaînes ne sont pas des types de valeurs. –

+1

Le problème est que 'new T (node)' est impossible. Les fonctions génériques peuvent uniquement invoquer des constructeurs par défaut de types paramétrés. – Gabe

+0

duplication possible de [problème constructeur C# générique new()] (http://stackoverflow.com/questions/840261/c-generic-new-constructor-problem) – Donnie

Répondre

6

new T a quelques vérifications de temps de compilation (évidemment comme vous avez couru dans), mais votre utilisation de celui-ci est basée sur des informations d'exécution. Même si vous connaissez typeof (int) .IsSubclassOf (XMLConstructible)) ne sera jamais vrai, le compilateur ne le sera pas, donc le new T doit compiler si vous allez sur ce chemin ou non. Au lieu d'utiliser new T, utilisez la réflexion pour créer l'instance. Un moyen facile est d'utiliser Activator.CreateInstance

ret = (T)Activator.CreateInstance(typeof(T), node); // this _will_ compile 
+1

+1 Avec quelques tests unitaires, pourrait faire une bonne approche. Il y aura quand même un rendement assez élevé, ce qui peut ou non être important. –

Questions connexes