2009-07-23 11 views
4

Je travaille dans un service Web C# avec une classe statique générique qui prend un type. Je me demandais pourquoi cela ne compile pas:affecter un type à une variable, utiliser une variable avec une classe statique générique

Type type1 = typeof(MySnazzyType); 
Assert.AreEqual(0, ConnectionPool_Accessor<type1>._pool.Count); 

Il donne cette erreur:

The type or namespace name 'type1' could not be found (are you missing a using directive or an assembly reference?)

Et ReSharper, quand je passe la souris sur type1 dans cette deuxième ligne de code, dit « nom de type ou espace de noms prévu ". Eh bien, type1est un type! C'est une variable de type Type! Elle ne fonctionne pas si je fais:

Type type1 = typeof(MySnazzyType); 
Assert.AreEqual(0, ConnectionPool_Accessor<typeof(type1)>._pool.Count); 

J'espérais céder mes types à un couple de différentes variables Type et il suffit d'utiliser les tests dans les différentes classes statiques génériques, au lieu de taper chaque fois MySnazzyType . Toutes les idées, ou suis-je coincé avec faire:

Assert.AreEqual(0, ConnectionPool_Accessor<MySnazzyType>._pool.Count); 

Edit: pour clarifier les choses, MySnazzyType est pas une classe générique, ni hériter d'une classe générique. La seule classe générique ici est ConnectionPool_Accessor.

Grâce au commentaire de Pavel "Essentiellement, votre problème est que C# est un langage typé statiquement", je sais maintenant que Ruby m'a gâté. ;)

+0

s/m'a gâté/m'a appris de mauvaises manières/;-) – Thorarin

Répondre

3

Tout d'abord, ReSharper est réellement correct. Ce n'est pas un type, c'est une variable . Certes, c'est une variable qui contient l'objet de réflexion correspondant à un type, mais cela ne suffit pas. Entre les parenthèses < ...>, vous devez écrire le nom d'un type, pas le nom d'un autre identificateur.

Vous pouvez construire des objets génériques par réflexion, et accéder à leurs propriétés, même statiques, vous devriez donc être capable de réécrire le code pour le faire, cependant, avez-vous regardé NUnit 2.5? D'après les dernières notes de publication, il semble que les classes de tests unitaires peuvent maintenant être génériques et vous pouvez spécifier avec un attribut sur la classe de test les types avec lesquels tester.

Cela vous permettra d'écrire quelque chose comme ça (note, je ne l'ai pas testé, je ne regardais les noms des nouveaux attributs dans la documentation):

[TestFixture(typeof(MySnazzyType))] 
[TestFixture(typeof(MyOtherSnazzyType))] 
public class Tests<T> 
{ 
    [Test] 
    public void PoolCount_IsZero() 
    { 
     Assert.AreEqual(0, ConnectionPool_Accessor<T>._pool.Count); 
    } 
} 
3

Les types génériques sont évalués à l'heure de compilation, et non au runtime. Comme il ne peut pas être déterminé au moment de l'exécution ce que sera type1, cette construction n'est pas autorisée.

C'est en fait ce que ReSharper dit: type1 est pas un type, il est une variable du type Type, (tout comme il pourrait être un objet du type String).

+0

Euh, avez-vous changé ce que vous vouliez dire? Peut-être que "les types génériques sont évalués à _runtime_, pas dans _compile time_". –

+0

Aussi, pourquoi est-il incapable de déterminer au type de compilation ce que sera 'type1', puisqu'il est écrit comme' typeof (MySnazzyType) '? –

+1

Non, il l'a écrit correctement. Le type générique dans votre cas est 'ConnectionPool_Accessor <>', et il est en effet résolu au moment de la compilation. Et à ce stade, il n'y a aucun moyen de dire à quel type 'type1' résoudra. Essentiellement, votre problème est que C# est un langage typé statiquement. –

1

L'attribut TestFixture devrait vous définissez en haut, mais juste pour le diable: si vous vouliez faire tout cela à l'exécution, vous pourriez le faire en utilisant la réflexion.

Type poolType = typeof(ConnectionPool_Accessor<>); 
Type snazzyType = typeof(MySnazzyType); // Or however you want to get the appropriate Type 
poolType.MakeGenericType(snazzyType); 

Vous pouvez ensuite passer à faire ce que vous voulez utiliser la réflexion sur poolType. Bien sûr, ce sera une douleur majeure dans le cul, sauf si vous utilisez le typage dynamique C# 4.0.

Questions connexes