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…

8 thoughts on “Contract classes and nested types within interfaces”

  1. I find it interesting in that you could further enforce a contract on a class. In that example, it certain wouldn’t make sense for any ICaseConverter to attempt to convert a null value. However, it complicates the C# 5 request I was going to make in regards to compile-time resolution of implicitly-defined interfaces. E.g. class Foo in an external assembly has the method: string Convert(string text) but doesn’t explicity define the interface. It should resolve as an ICaseConverter without the need for a wrapper.

    Like

  2. Not being so passionate about “one top-level class per file”, I don’t find the current situation so “dirty”. :) But I agree, it’s curious and perhaps a little unfortunate that interfaces can’t have nested types.

    For that matter, in hindsight I find it curious we have interfaces at all. It seems to me that an interface is little more than an abstract class without any implementation at all. So C# _could_ have just had abstract classes (with the associated requirement that a class can inherit at most one class with any implementation…any number of “empty” abstract classes could be inherited). And of course, abstract classes can have nested types. :)

    As far as Chris’s comment about implicit interface conversion: obviously, “dynamic” addresses this to some extent. So what happens if you try to cast a reference from a “dynamic” variable to an interface? (I’d test it myself, but unfortunately am unable to have VS2010 installed at the moment). I’m assuming that currently, the usual type conversion rules apply, and that the instance, not being an implementation of the interface, can’t be cast successfully.

    I’ve seen a few requests from other people for the “duck typing” along these lines you’re asking for. But I’d be surprised if it shows up as a C# feature. Even “dynamic” was a surprise to me, and that was for specific interop goals as far as I can tell.

    Duck typing would be strictly a feature internal to the language itself, and seems contrary to the usual “strong typing” philosophy that guides most of C#’s design. I would worry most about accidental implementation of some interface; class members of the same name, but without the expected semantics of those found in the interface.

    At least, that’s my impression. I could be wrong. :)

    Like

  3. I just tested out nesting a class within an interface in vb. It works, unless the interface has co/contra-variant generic parameters.

    I hope the next iteration of C# and VB include syntax especially for contracts. The language-independent stuff works, but it’s not very concise.

    Like

  4. Long influenced by Java, I generally prefer one top-level _public_ type. As your implementation is internal, I do not feel that it is too bad or dirty to reside within the same file. As you said, it is essentially metadata that belongs together. In the end, you should partition your code in a manner that is useful for understanding and maintaining rather than inflexible rules.

    As a side note, my first reaction was disappointment that C# still does not allow generic attributes. Using typeof in such cases always feels like a hack.

    Like

  5. @Pete: interfaces are abstract classes without implementation? Yes this the way the IL metadata describes interfaces ;-)

    @Jon: A nested type is in reality only a concatenated type name which means that the type name is prepended with the enclosing type with + so the resulting type name would be ICaseConverter+InvariantUpperCaseFormatter. The visibility of the type can be the same as the enclosng type but no more. This is the reason why VB.NET can support it. Personally I find if clarity has reached a sufficient level it is ok from my point of view.

    But to make things more interesting you can have interfaces with default implementations in the version post CLR 4.0. That would give you both:
    An interface and an implemenation you can override when needed but you implement always against an interface.

    Yours,
    Alois Kraus

    Like

  6. @Alois:

    That may be true for interfaces (which can have only public members anyway), but types nested within classes are more than just a naming convention — they have access to private members of the containing class (given an instance of course for access to non-static members, we’re still talking .NET nested classes and not Java inner classes).

    Like

Leave a comment