I prefer exceptions over asserts because if it's supposed to be that way and isn't, I want to know about it so I can fix it, and the coverage we get in debug mode is nowhere near real-life usage or coverage, so just using Debug.Assert doesn't do enough.
Using asserts means that you won't add bloat to your release code, but it means you only get to see when and why these contracts get broken if you catch them at it in a debug build.
Using exceptions means you get to see the contract breaking whenever it happens, debug or release, but it also means your release build contains more checks and code.
You could go with an inbetween approach and use Trace to trace out your pre and post conditions to some kind of application log, which you could use to debug problems. However, you'd need a way of harvesting these logs to learn what issues your users are encountering. THere is also the possibility of combing this with exceptions so you get exceptions for the more severe problems.
The way I see it though, is that if the contract is worth enforcing then its worth throwing an exception when it breaks. I think that's somewhat down to opinion and target application though. If you do throw exceptions, you probably want some form of incident reporting system that provides crash reports when raised exceptions are left unhandled.