4

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

4

3 回答 3

3

泛型类型在编译时评估,而不是在运行时评估。由于无法在运行时确定type1将是什么,因此不允许使用此构造。

这实际上是 Resharper 所说的:type1不是 Type,它是 type 的变量Type,(就像它可能是 type 的对象一样String)。

于 2009-07-23T21:40:14.227 回答
3

首先,ReSharper 实际上是正确的。它不是类型,而是变量。当然,它是一个变量,它保存着对应于一种类型的反射对象,但这还不够。

在 <...> 括号之间,您必须写一个类型的名称,而不是任何其他标识符的名称。

但是,您可以通过反射构造通用对象,并访问它们的属性,甚至是静态属性,因此您应该能够重写代码来做到这一点,但是,您看过 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);
    }
}
于 2009-07-23T21:41:46.563 回答
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 动态类型,否则这将是一个很大的麻烦。

于 2009-07-23T22:13:10.977 回答