将类型赋值给变量,使用带有泛型静态类的变量

时间:2009-07-23 21:36:44

标签: c# generics types static-typing

我正在使用一个带有类型的通用静态类的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已经破坏了我。 ;)

3 个答案:

答案 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动态类型,否则这将是一个主要的痛苦。