33

I'd like to specify a contract for this generic interface, using Code Contracts:

interface IRandomWriteAccessible<T>
{
    T this[uint index] { set; }
    uint Length { get; }
}

The documentation says to use the ContractClass attribute when specifying a contract for an interface. However, the compiler will complain about this:

[ContractClass(typeof(IRandomWriteAccessibleContract<T>))]
//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     <-- compiler error
interface IRandomWriteAccessible<T> { … }

[ContractClassFor(typeof(IRandomWriteAccessible<T>))]
//                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          <-- compiler error
sealed class IRandomWriteAccessibleContract<T> : IRandomWriteAccessible<T> { … }

It seems that type parameters cannot be used with attributes.

How do I write a contract for my generic interface? Or is this not possible with Code Contracts?

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • 2
    I have not verified this, but remove the `T` from your attribute usage as follows: `[ContractClass(typeof(IRandomWriteAccessibleContract<>))]` – Steve Guidi Jan 27 '10 at 23:05

2 Answers2

45

As mentioned by other comments in this question, you should remove the generic type identifier from your attribute usage as it can not be resolved at compile time:

[ContractClass(typeof(IRandomWriteAccessibleContract<>))] 
Steve Guidi
  • 19,700
  • 9
  • 74
  • 90
  • 5
    I looked this up in the C# language specification out of curiosity: The relevant chapters are _14.5.11 (typeof operator)_ and _25.5 (generics: constructed types)_, if anyone else is interested. – stakx - no longer contributing Jan 28 '10 at 05:14
  • 15
    Also, if the generic class you're typeof()'ing takes more than one parameter, you have to use commas; for instance, typeof(YourType<,>), where YourType takes two type parameters. –  Oct 17 '10 at 09:43
1

Good question, but you can see the technical reasons behind this limitation, right?

The reason that you can't specify the ContractClass is because Blah<T> is not a class.

If you can make an interface for a concrete class by specifying a value for T, even though I'm sure this is sub-optimal.

John Gietzen
  • 48,783
  • 32
  • 145
  • 190