1

I have an abstract class whose constructor requires a parameter. The parameter cannot be null.

// the abstract class
[ContractClass(typeof(AbstractClassContract))]
public abstract class AbstractClass
{
   // Constructor with required parameter
   protected AbstractClass(SqlConnection connection)
   {
      Contract.Requires(connection != null);
      Connection = connection;
   }

   protected SqlConnection Connection { get; set; }

   public abstract string GetSomething();
}

The abstract class has a contract class for checking pre/post-conditions on abstract members.

// the contract class
[ContractClassFor(typeof(AbstractClass))]
public abstract class AbstractClassContract
{
   public override string GetSomething()
   {
      Contract.Ensures(Contract.Result<string>() != null);
      return default(string);
   }
}

The above code doesn't compile because of the error 'AbstractClass' does not contain a constructor that takes 0 arguments.

I can add a constructor, like below, and the code will compile and seems to work.

   public AbstractClassContract(SqlConnection connection)
      : base(connection)
   { }

But is this a valid constructor for a contract class? Will it cause a problem in some situation? My concern is that the parameter is ultimately required by the abstract class's constructor.

If it is valid, then how is .NET getting around the required parameter limitation?

Keith
  • 20,636
  • 11
  • 84
  • 125

1 Answers1

3

It's been a while since I looked at Code Contracts, but I'd expect that your contract class was never actually instantiated. Instead, the contracts checker will basically suck the code from your contract class into each concrete subclass.

So if I'm write, your constructor in AbstractClassContract should be fine. Or you could just use new SqlConnection("this is never called") to be clearer :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    You're right -- I used a debugger and confirmed that the contract class's constructor is never actually called. The pre/post-condition checks from the contract class are run as if they were part of the concrete subclass, as you suggested (even the stack trace indicates such). So the contract class's constructor is just for show... I assume to make the compiler happy. – Keith Jun 26 '14 at 20:49