Contract classes and nested types within interfaces
I've just been going through some feedback for the draft copy of the second edition of C# in Depth. In the contracts section, I have an example like this:
[ContractClass(typeof(ICaseConverterContracts))]
public interface ICaseConverter
{
string Convert(string text);
}
[ContractClassFor(typeof(ICaseConverter))]
internal class ICaseConverterContracts : ICaseConverter
{
string ICaseConverter.Convert(string text)
{
Contract.Requires(text != null);
Contract.Ensures(Contract.Result<string>() != null);
return default(string);
}
private ICaseConverterContracts() {}
}
public class InvariantUpperCaseFormatter : ICaseConverter
{
public string Convert(string text)
{
return text.ToUpperInvariant();
}
}
The point is to demonstrate how contracts can be specified for interfaces, and then applied automatically to implementations. In this case, ICaseConverter is the interface, ICaseConverterContracts is the contract class which specifies the contract for the interface, and InvariantUpperCaseFormatter is the real implementation. The binary rewriter effectively copies the contract into each implementation, so you don't need to duplicate the contract in the source code.
The reader feedback asked where the contract class code should live - should it go in the same file as the interface itself, or in a separate file as normal? Now normally, I'm firmly of the "one top-level type per file" persuasion, but in this case I think it makes sense to keep the contract class with the interface. It has no meaning without reference to the interface, after all - it's not a real implementation to be used in the normal way. It's essentially metadata. This does, however, leave me feeling a little bit dirty. What I'd really like to be able to do is nest the contract class inside the interface, just like I do with other classes which are tightly coupled to an "owner" type. Then the code would look like this:
[ContractClass(typeof(ICaseConverterContracts))]
public interface ICaseConverter
{
string Convert(string text);
[ContractClassFor(typeof(ICaseConverter))]
internal class ICaseConverterContracts : ICaseConverter
{
string ICaseConverter.Convert(string text)
{
Contract.Requires(text != null);
Contract.Ensures(Contract.Result<string>() != null);
return default(string);
}
private ICaseConverterContracts() {}
}
}
public class InvariantUpperCaseFormatter : ICaseConverter
{
public string Convert(string text)
{
return text.ToUpperInvariant();
}
}
That would make me feel happier - all the information to do with the interface would be specified within the interface type's code. It's possible that with that as a convention, the Code Contracts tooling could cope without the attributes - if interface IFoo contains a nested class IFooContracts which implements IFoo, assume it's a contract class and handle it appropriately. That would be sweet.
You know the really galling thing? I'm pretty sure VB does allow nested types in interfaces...