我正在使用一个带有类型的通用静态类的C#Web服务。我想知道为什么这不编译:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<type1>._pool.Count);
它给出了这个错误:
找不到类型或命名空间名称'type1'(您是否缺少using指令或程序集引用?)
当我将鼠标悬停在第二行代码中的type1
时,ReSharper会说“预期类型或命名空间名称”。好吧,type1
是类型!它是Type
类型的变量!如果我这样做也不起作用:
Type type1 = typeof(MySnazzyType);
Assert.AreEqual(0, ConnectionPool_Accessor<typeof(type1)>._pool.Count);
我希望将我的类型分配给几个不同的Type
变量,并且只是在测试不同的通用静态类时使用它们,而不是每次都输入MySnazzyType
。任何想法,或者我坚持做:
Assert.AreEqual(0, ConnectionPool_Accessor<MySnazzyType>._pool.Count);
编辑:澄清一下,MySnazzyType
不是一个泛型类,它也不是从泛型类继承的。这里唯一的通用类是ConnectionPool_Accessor
。
感谢Pavel的评论“基本上,你的问题是C#是一种静态类型语言”,我现在知道Ruby已经破坏了我。 ;)
答案 0 :(得分:3)
通用类型在编译时评估,而不是在运行时中评估。由于无法在运行时确定type1
将是什么,因此不允许使用此构造。
这实际上是Resharper所说的:type1
不是Type,它是Type
类型的变量,(就像它可能是String
类型的对象一样)。
答案 1 :(得分:3)
首先,ReSharper实际上是正确的。它不是类型,它是变量。当然,它是一个变量,它持有与一个类型相对应的反射对象,但这还不够。
在&lt; ...&gt;之间括号,你必须写一个类型的名称,而不是任何其他标识符的名称。
然而,您可以通过反射构建通用对象,并访问它们的属性,甚至是静态属性,因此您应该能够重写代码来执行此操作,但是,您是否查看过NUnit 2.5?
从最新的发行说明中看来,单元测试类现在可以是通用的,您可以在测试类中使用属性指定要测试它的类型。
这将允许你写这样的东西(注意,我没有测试过这个,我只查找了文档中新属性的名称):
[TestFixture(typeof(MySnazzyType))]
[TestFixture(typeof(MyOtherSnazzyType))]
public class Tests<T>
{
[Test]
public void PoolCount_IsZero()
{
Assert.AreEqual(0, ConnectionPool_Accessor<T>._pool.Count);
}
}
答案 2 :(得分:1)
TestFixture
属性应该为你设置,但只是为了它:如果你想在运行时完成所有这些,你可以使用反射。
Type poolType = typeof(ConnectionPool_Accessor<>);
Type snazzyType = typeof(MySnazzyType); // Or however you want to get the appropriate Type
poolType.MakeGenericType(snazzyType);
然后,您可以使用poolType
上的反射继续执行任何操作。当然,除非你使用C#4.0动态类型,否则这将是一个主要的痛苦。