C#泛型铸造
Visual sutdio 2008能够自动创建单元测试存根。我用它来创建一些基本的单元测试,但我的东西迷惑:C#泛型铸造
private class bla : BaseStoreItem
{
//
}
/// <summary>
///A test for StoreData
///</summary>
public void StoreDataTestHelper<T>() where T : BaseStoreItem
{
FileStore<T> target = new FileStore<T>(); // TODO: Initialize to an appropriate value
BaseStoreItem data = new bla();
target.StoreData(data);
}
[TestMethod()]
public void StoreDataTest()
{
//Assert.Inconclusive("No appropriate type parameter is found to satisfies the type constraint(s) of T. " +
// "Please call StoreDataTestHelper<T>() with appropriate type parameters.");
StoreDataTestHelper<bla>();
}
为什么我会收到“错误:无法转换类型‘StorageUnitTests.FileStoreTest.bla’到‘T’”当T键入“bla”?
我知道“bla”不是一个好的函数名,但它只是一个例子。
为什么不那样呢? (它没有多大SENCE创建StoreDataTestHelper的BLA内的一个实例,如果你有机会到T)
public void StoreDataTestHelper<T>() where T : BaseStoreItem, new()
{
FileStore<T> target = new FileStore<T>();
T data = new T();
target.StoreData(data);
}
因为,如果T
是DerivedStoreItem
(继承BaseStoreItem
),您就违反了类型FileStore<T>
通过存储BaseStoreItem
。
这是有道理的。通过指定T: BaseStoreItem
,您确保T
将作为基类的BaseStoreItem
类型,而不是它必然是BaseStoreItem
。因此,如果T后来被设置为来自BaseStoreItem
的某种类型,那么您的target.StoreData(data);
行将执行非法操作。
虽然你的情况,你只用T
集调用StoreDataTestHelper
到bla
,C#的typechecker需要确保为StoreDataTestHelper
的代码是类型安全的一般。这是一种强类型语言的好处之一:在制作它们之前捕获潜在的输入错误。
when T is type "bla"
你的上述条件仅适用于当前的情况下也是如此,但我可以创造一个诺特尔类
public class Bla2: BaseStoreItem {...
然后Bla2 <> BLA ...,既不Bla2从BLA派生,所以如果我尝试使用
StoreDataTestHelper<Bla2>();
这是错误的,编译器是足够聪明,明白,在这种情况下它不会工作,计算机语言是不喜欢英语,他们正在创建工作exactl y在所有条件下都相同。而且它们的设计使语言规则在所有情况下都是正确的。如果他们不同,你会发现混乱发现错误的地方。
我认为它应该是Activator.CreateInstance()而不是新的T().. –
2010-03-26 10:01:19
@Akash为什么? Activator.CreateInstance使用反射,它很慢。它认为新的T()更优雅。 – gsharp 2010-03-26 10:11:59
gsharp,对不起,我错过了,在你的代码中的new()约束,因为没有指定new() – 2010-03-26 10:19:13