Nippysaurus
Nippysaurus

Reputation: 20378

C# Generics Casting

Visual Studio 2008 has the ability to automatically create unit test stubs. I have used this to create some basic unit tests, but I am confused by something:

  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>();
     }

Why do I get "Error: Cannot convert type 'StorageUnitTests.FileStoreTest.bla' to 'T'" when T is type "bla"?

I know "bla" is not a good function name, but its just an example.

Upvotes: 4

Views: 471

Answers (4)

Akash Kava
Akash Kava

Reputation: 39916

when T is type "bla"

Your above condition holds true only for current case, but I can create a nother class

public class Bla2: BaseStoreItem {...

Then Bla2 <> bla ... , neither Bla2 is derived from bla, so if I try to use

StoreDataTestHelper<Bla2>(); 

This is wrong, compiler is smart enough to understand that in this condition it will not work, computer languages are not like english, they are created to work exactly same in all conditions. And they are designed so that rules of language are correct in all cases. If they differ you will have chaos finding where the error is.

Upvotes: 1

smehmood
smehmood

Reputation: 1944

This makes sense. By specifying T: BaseStoreItem, you have guaranteed that T will be a type the has BaseStoreItem as a base class, and NOT that it will necessarily be a BaseStoreItem. Therefore, if T is later set to be some type that derives from BaseStoreItem, your target.StoreData(data); line would be performing an illegal operation.

Although in your case you only invoke StoreDataTestHelper with T set to bla, C#'s typechecker needs to make sure that the code for StoreDataTestHelper is type-safe in general. This is one of benefits to a strongly-typed language: it catches potential typing mistakes before you make them.

Upvotes: 0

Tormod Fjeldsk&#229;r
Tormod Fjeldsk&#229;r

Reputation: 6002

Because, if T is DerivedStoreItem (inheriting BaseStoreItem), you would be violating the type of FileStore<T> by storing a BaseStoreItem.

Upvotes: 0

gsharp
gsharp

Reputation: 27927

why not that way? (It doesn't make much sence to create an instance of bla inside of StoreDataTestHelper if you have access to T)

 public void StoreDataTestHelper<T>() where T : BaseStoreItem, new()
 {
     FileStore<T> target = new FileStore<T>(); 

     T data = new T();

     target.StoreData(data);
 }

Upvotes: 4

Related Questions