I have a generic interface for a mathematics library, something like this:
[ContractClass(typeof(MathsDoubleContracts))]
public interface IMaths<T>
{
T SomeFunction(T n);
}
This enables me to create an IMaths<double>
, IMaths<decimal>
, etc. (although at first I only need the double
version).
I'd like to set up code contracts. At present I've done this:
[ContractClassFor(typeof(IMaths<double>))]
public abstract class MathsDoubleContracts : IMaths<double>
{
public double SomeFunction(double n)
{
// Always positive
Contract.Ensures(0 <= Contract.Result<double>());
return double.NaN;
}
}
This seems to work, but I'm rather surprised that it does (given that I'm specifying contracts on IMaths<double>
rather than IMaths<T>
).
I'm left wondering:
[ContractClass(typeof(MathsDoubleContracts))]
and [ContractClass(typeof(MathsDecimalContracts))]
attributes on IMaths<T>
)? Is this a sensible thing to do?IMathsDouble
where all the functions are defined in terms of doubles, adding IMathsDecimal
later)?Can you bring an example please.
No. It does not allow multiple. Ref here.
AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
Note AllowMultiple = false
.
Yes, although generics might provide some little benefit. Your interface is not really generic. I cannot use IMaths<File>
for example. I actually answered a different but related question here.
You may add restrictions such as where T : ...
but that also will not do since you have to limit to only int
, double
while you can only do where T : struct
which is not the same thing. Here generics is mere a decoration and the abstraction of IMaths<T>
cannot be used as it is (or can it? can depend on your code) and you need concrete classes or interfaces.
A sub-interface is a safe option here
interface IntMaths : IMaths<int>
{
}