9

I can have a nested contracts type for a non-generic interface:

[ContractClass(typeof(Foo.FooContracts))]
public interface IFoo
{
    string Bar(object obj);
}

But it complains when I try to do the same thing with a generic interface:

[ContractClass(typeof(Foo.FooContracts<>))]
public interface IFoo<T>
{
    string Bar(T obj);
}

The warning is:

The contract class Foo+FooContracts`1 and the type IFoo`1 must have the same declaring type if any.

It compiles without a warning if I get FooContracts out of the Foo class.

  • Why does that limitation exist for generic interfaces?
  • Why doesn't that limitation exist for non-generic ones?
Şafak Gür
  • 7,045
  • 5
  • 59
  • 96
  • 1
    As an experiment, I nested a non-generic `FooContracts` within a generic `Foo` class, and set everything up as above. In addition to the message you've shown, this also now generates "The contract class 'Foo`1+FooContracts' and the type 'IFoo`1' must agree on all generic parameters." I'm wondering if this is the start of a quagmire that they're trying to avoid by having the rule you've found. – Damien_The_Unbeliever Sep 25 '13 at 13:54
  • @Damien: Good idea! I think it's highly possible since it also explains why it doesn't occur with non-generic interfaces. – Şafak Gür Sep 26 '13 at 08:34

2 Answers2

1

The reason the limitation exists is that we need to copy contracts from the declaration point to the insertion points and that gets much more complicated if there are generic surrounding classes. There really is no need to have contract classes nested inside other types that I see.

Manuel Fahndrich
  • 665
  • 4
  • 12
0

This code compiles on my machine (VS2012, .NET 4.5)

[ContractClass(typeof(Foo.FooContracts<>))]
public interface IFoo<T> {
    string Bar(T obj);
}

[ContractClassFor(typeof(IFoo<>))]
public class Foo {
    public class FooContracts<T> : IFoo<T> {
        public string Bar(T obj) {
            throw new NotImplementedException();
        }
    }
}

I added the ContractClassForAttribute, but I can take it out.

edit: also the ContractClassForAttribute can be applied to the outer or inner class. I don't know which is correct, but neither location affects compilation

jrv
  • 496
  • 4
  • 8
  • **If I use it like you suggest: 1.** Type ``IFoo`1`` specifies the class ``Foo+FooContracts`1`` as its contract class, but that class does not point back to this type. **2.** `Foo` should be an abstract class **3.** Class `Foo` is annotated as being the contract for the interface ``IFoo`1`` but doesn't implement the interface. **If I apply the attribute to the inner class: 1.** `Foo` should be an abstract class **2.** The contract class ``Foo+FooContracts`1`` and the type ``IFoo`1`` must have the same declaring type if any. – Şafak Gür Sep 26 '13 at 10:30