起订量正在触发代码合同?

发布于 2024-12-25 18:31:25 字数 475 浏览 1 评论 0原文

给出这段代码:

[ContractClass(typeof(DogContract))]
public interface IDog {
  void Eat(object obj);
}

[ContractClassFor(typeof(IDog))]
internal abstract DogContract : IDog {
  public void Eat(object obj) {
    Contract.Requires<ArgumentNullException>(obj != null);
  }
}

var dogMock = new Mock<IDog>();
dogMock.Object.Eat(null); // Throws ArgumentNullException

似乎重写器以某种方式将其行为放入模拟对象中,这是我真正没想到的。我不认为这是一个真正的问题,只是出乎意料。有人知道这是怎么发生的吗?

Given this code:

[ContractClass(typeof(DogContract))]
public interface IDog {
  void Eat(object obj);
}

[ContractClassFor(typeof(IDog))]
internal abstract DogContract : IDog {
  public void Eat(object obj) {
    Contract.Requires<ArgumentNullException>(obj != null);
  }
}

var dogMock = new Mock<IDog>();
dogMock.Object.Eat(null); // Throws ArgumentNullException

It seems like the rewriter is somehow putting its behavior into the mocked object, which I didn't really expect. I don't think its a real problem, just unexpected. Anyone know how this is happening?

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

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

发布评论

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

评论(1

妥活 2025-01-01 18:31:25

“调用站点需要检查”就可以了。然后,重写器会将前提条件放入调用者代码中,而不是实现中。因此,即使模拟对象中的代码无法重写(它是在运行时生成的),调用者中的代码也可以重写。

生成的代码如下所示,不带调用站点 Requires:

private static void Main(string[] args)
{
    Mock<IDog> m = new Mock<IDog>();
    m.Object.Eat(null);
}

且带:

private static void Main(string[] args)
{
    Mock<IDog> m = new Mock<IDog>();
    IDog.V$Eat(m.Object, null);
}

IDog 是一个静态类,包含 IDog 接口中的所有方法以及先决条件。 Eat 的样子如下:

internal static void V$Eat(IDog @this, object obj)
{
    __ContractsRuntime.Requires<ArgumentNullException>(
                      obj != null, null, "obj != null");
    @this.Eat(obj);
}

这样,即使类中的代码无法重写,前置条件也会被调用。

"Call-site Requires checking" will do it. The rewriter will then put the preconditions into the caller code and not the implementations. So, even though the code in the mocked object can't have been rewritten (it's generated at runtime), the code in the caller can be.

Here's what the generated code looks like without call-site Requires:

private static void Main(string[] args)
{
    Mock<IDog> m = new Mock<IDog>();
    m.Object.Eat(null);
}

And with:

private static void Main(string[] args)
{
    Mock<IDog> m = new Mock<IDog>();
    IDog.V$Eat(m.Object, null);
}

IDog is a static class that contains all the methods from the IDog interface, along with the preconditions. Here is what Eat looks like:

internal static void V$Eat(IDog @this, object obj)
{
    __ContractsRuntime.Requires<ArgumentNullException>(
                      obj != null, null, "obj != null");
    @this.Eat(obj);
}

So this way, the preconditions will be called even if the code in the class can't have been rewritten.

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