Say I have the following
public T Exam开发者_如何学JAVAple(Func<T> f)
{
Contract.Requires(f != null);
Contract.Requires(f() != null); // no surprise, this is an error
...
}
Is there any way to specify that my Func<T>
parameters must obey some contracts?
In general, that seems like a problematic requirement since invoking f
may introduce side effects so specifying a contract could affect what the method does.
As the implementer of the Code Contracts library one could introduce wrapper code that checks to see if the value of f
obeys the contract when it is invoked in the context of your method (to avoid introducing a spurious method call). This is problematic for a couple of reasons:
- The method might never invoke
f
, so the caller could violate the contract and not get busted. - The method could call
f
only after doing some other work which might be invalid given that the call tof
didn't satisfy the specification.
If f
had no side effects then these wouldn't be problems, but in the presence of side effects dealing with 1 by always calling f
wouldn't work and calling f
before doing any work to deal with 2 also wouldn't fly.
So, in conclusion I don't think that this is possible (in the context of native code contracts) and with good reason.
If you mean that the passed method should check itself whether e.g. the parameter is not null, no you cannot do this. Contracts still simply add code to the method body.
What you can however do is wrap the delegate into a different delegate, e.g.:
public T Example<T, TResult>(Func<T, TResult> f)
where T : class
where TResult : class
{
Contract.Requires(f != null);
f = WrapWithContracts(f);
// ...
}
private Func<T, TResult> WrapWithContracts<T, TResult>(Func<T, TResult> f)
where T : class
where TResult : class
{
return p =>
{
Contract.Requires(p != null);
Contract.Ensures(Contract.Result<TResult>() != null);
var result = f(p);
return result;
};
}
This way you can introduce code contracts yourself.
If (as here) it's specifically nullity you're concerned with, ReSharper (from 4.0 onwards) has support for Annotations such as CanBeNull
and NotNull
, which can be placed as attributes on methods, after which R# can warn about possible null dereferencing operations.
精彩评论