我应该对通用接口使用类型化代码契约吗?
我有一个数学库的通用接口,如下所示:
[ContractClass(typeof(MathsDoubleContracts))]
public interface IMaths<T>
{
T SomeFunction(T n);
}
这使我能够创建 IMaths
、IMaths
等(尽管一开始我只需要 double
版本)。
我想建立代码合同。目前我已经这样做了:
[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;
}
}
这似乎有效,但我对此感到非常惊讶(鉴于我在 IMaths
而不是 IMaths
)。
我想知道:
- 我可以在通用接口上指定多个合约类,每个合约类对应我想要使用的每种特定类型(例如同时具有
[ContractClass(typeof(MathsDoubleContracts))]
和
属性?这是明智之举吗?IMaths
上的 [ContractClass(typeof(MathsDecimalContracts))] - 我最好完全不使用通用接口(即从
IMathsDouble
开始,其中所有函数都以双精度定义,添加IMathsDecimal< /code> 稍后)?
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:
- Can I specify multiple contract classes on a generic interface, one for each specific type I want to use (e.g. have both
[ContractClass(typeof(MathsDoubleContracts))]
and[ContractClass(typeof(MathsDecimalContracts))]
attributes onIMaths<T>
)? Is this a sensible thing to do? - Would I be better off not using generic interfaces at all (i.e. start with, say,
IMathsDouble
where all the functions are defined in terms of doubles, addingIMathsDecimal
later)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Q1
请举个例子。
编辑
否。它不允许多个。请参考此处。
注意
AllowMultiple = false
。Q2
是的,尽管仿制药可能会带来一些小好处。你的界面并不是很通用。例如,我无法使用
IMaths
。我实际上回答了一个不同但相关的问题此处。您可以添加诸如
where T : ...
之类的限制,但这也行不通,因为您必须限制为仅int
,double
while你只能做where T : struct
这不是同一件事。这里泛型仅仅是一种装饰,IMaths
的抽象不能按原样使用(或者可以吗?可以取决于您的代码),并且您需要具体的类或接口。子接口是一个安全的选择
Q1
Can you bring an example please.
EDIT
No. It does not allow multiple. Ref here.
Note
AllowMultiple = false
.Q2
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 onlyint
,double
while you can only dowhere T : struct
which is not the same thing. Here generics is mere a decoration and the abstraction ofIMaths<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
我通过将契约应用于通用接口来做到这一点,然后在运行时推断契约类型。
然而,我的问题是在“通用代码”程序集中定义一个基本抽象接口,该接口应用于 IService 类型的对象,然后继承该接口以实现我需要的类型特定实现。
但是我不必指定特定于类型的实现,我可以简单地(通过依赖项注入)在运行时确定契约和对象类型...
代码契约继承
我认为我的问题是使其“可移植”
I'm kind of doing this by applying a contract to a generic interface, the contract type is then inferred at runtime.
My problem however is defining a base abstract interface in a "common code" assembly which applies to an object of type IService then inherit that for type specific implementations that i require.
however I don't have to specify a type specific implementation i could simply (through dependency injection) determine the contract and object type at runtime ...
Code contract inheritance
I think my issue is making it "portable"