Pregunta

Estoy trabajando en un servicio web de C# con una clase estática genérica que toma un tipo. Me preguntaba por qué esto no se compila:

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

Da este error:

No se puede encontrar el tipo o el nombre del espacio de nombres 'Tipo1' (¿se está perdiendo una directiva de uso o una referencia de ensamblaje?)

Y resharper, cuando me desplazé type1 En esa segunda línea de código, dice "se espera el nombre o el nombre del espacio de nombres". Bien, type1 es ¡un tipo! Es una variable de tipo Type! Tampoco funciona si lo hago:

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

Esperaba asignar mis tipos a un par de diferentes Type variables y simplemente use las que prueban las diferentes clases estáticas genéricas, en lugar de escribir MySnazzyType cada vez. Cualquier idea, o estoy atrapado con hacer:

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

Editar: para aclarar, MySnazzyType es no Una clase genérica, ni hereda de una clase genérica. La única clase genérica aquí es ConnectionPool_Accessor.

Gracias al comentario de Pavel "Esencialmente, su problema es que C# es un lenguaje escrito", ahora sé que Ruby me ha mimado. ;)

¿Fue útil?

Solución

En primer lugar, Resharper es realmente correcto. No es un escribe, es un variable. De acuerdo, es una variable que mantiene el objeto de reflexión que corresponde a un tipo, pero eso no es suficiente.

Entre los brackets <...>, debe escribir el nombre de un tipo, no el nombre de ningún otro identificador.

Sin embargo, puede construir objetos genéricos a través de la reflexión y acceder a sus propiedades, incluso a los estáticos, por lo que debería poder reescribir el código para hacerlo, sin embargo, ¿ha visto Nunit 2.5?

De las últimas notas de versión, parece que las clases de prueba unitaria ahora pueden ser genéricas, y puede especificar con un atributo en la clase de prueba con qué tipos de probarlo.

Esto le permitiría escribir algo como esto (nota, no he probado esto, solo busqué los nombres de los nuevos atributos en la documentación):

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

Otros consejos

Los tipos genéricos se evalúan en tiempo de compilación, no en tiempo de ejecución. Ya que no se puede determinar en tiempo de ejecución, lo que type1 Será, esta construcción no está permitida.

Esto es en realidad lo que dice Resharper: type1 no es un tipo, es una variable del tipo Type, (así como podría ser un objeto del tipo String).

los TestFixture El atributo debería configurarlo, pero solo por lo que diablos: si quisiera hacer todo esto en tiempo de ejecución, podría hacerlo usando la reflexión.

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

Luego podría proceder a hacer lo que quieras usando la reflexión sobre poolType. Por supuesto, eso será un gran dolor en el trasero a menos que use la escritura dinámica C# 4.0.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top