我应该对通用接口使用类型化代码契约吗?

发布于 2024-12-25 12:46:33 字数 1103 浏览 2 评论 0原文

我有一个数学库的通用接口,如下所示:

[ContractClass(typeof(MathsDoubleContracts))]
public interface IMaths<T>
{
    T SomeFunction(T n);
}

这使我能够创建 IMathsIMaths 等(尽管一开始我只需要 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上指定合约;)。

我想知道:

  1. 我可以在通用接口上指定多个合约类,每个合约类对应我想要使用的每种特定类型(例如同时具有 [ContractClass(typeof(MathsDoubleContracts))]IMaths 上的 [ContractClass(typeof(MathsDecimalContracts))] 属性?这是明智之举吗?
  2. 我最好完全不使用通用接口(即从 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:

  1. 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 on IMaths<T>)? Is this a sensible thing to do?
  2. 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, adding IMathsDecimal later)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

提赋 2025-01-01 12:46:33

Q1

请举个例子。

编辑

否。它不允许多个。请参考此处

AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]

注意AllowMultiple = false

Q2

是的,尽管仿制药可能会带来一些小好处。你的界面并不是很通用。例如,我无法使用 IMaths 。我实际上回答了一个不同但相关的问题此处

您可以添加诸如 where T : ... 之类的限制,但这也行不通,因为您必须限制为仅 int, double while你只能做 where T : struct 这不是同一件事。这里泛型仅仅是一种装饰,IMaths 的抽象不能按原样使用(或者可以吗?可以取决于您的代码),并且您需要具体的类或接口。

子接口是一个安全的选择

interface IntMaths : IMaths<int>
{

}

Q1

Can you bring an example please.

EDIT

No. It does not allow multiple. Ref here.

AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]

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 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>
{

}
悟红尘 2025-01-01 12:46:33

我通过将契约应用于通用接口来做到这一点,然后在运行时推断契约类型。

然而,我的问题是在“通用代码”程序集中定义一个基本抽象接口,该接口应用于 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"

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文