1

假设我有以下不允许更改的课程:

public class C
{
    public C() { CreateSideEffects(); }
    public void M() { DoSomethingUseful(); }
}

我必须在不调用构造函数的情况下调用 M 。可能吗?

4

5 回答 5

8

即使这不是一个好主意,是的,我们可以 ;) 使用FormatterServices。获取未初始化对象

C uninitializedC = (C)FormatterServices.GetUninitializedObject(typeof(C));
uninitializedC.M();
于 2009-11-18T16:11:42.053 回答
7

不行,因为C.M()是实例方法,所以需要创建实例,也就是调用构造函数。

C您的团队拥有的课程吗?如果是这样,但你被命令不要管它,你最好游说以下任何一个:

  1. 那些需要重构和删除的副作用
  2. C.M()方法功能移出到另一个类或变为静态。

如果C来自第 3 方,您将遇到麻烦,并且可能必须以您拥有的方法复制C.M()功能。

于 2009-11-18T15:41:28.683 回答
4

是的你可以!

不用说这是一个糟糕的设计,但是您已经知道并且无法更改它。如果必须,您可以尝试部分模拟课程。

编辑:刚刚意识到我的示例使用 Java 而不是 C#。但是,@Guillaume 提供了 C# 的代码示例。显然,它甚至内置在运行时 API 中!

在 Java 中,使用Mockito,这确实有效:

C c = Mockito.mock(C);
Mockito.doCallRealMethod().when(c).M();
// If M() isn't a void method
// when(c.M()).thenCallRealMethod();
c.M();

但是,在这种情况下M(),不能依赖于构造函数中设置的任何状态。

有关部分模拟的更多信息,请查看此常见问题解答问题。但是,模拟主要用于测试。

于 2009-11-18T15:49:29.307 回答
1

为了调用实例方法,您需要一个实例!而且 - 有充分的理由 - 获得一个的唯一方法是通过构造函数。否则,由于尚未进行初始化,整个对象可能处于不确定或无用状态。所以就算有什么hack,也不是什么好选择!

唯一可以在没有实例的情况下调用的类成员是静态方法。

于 2009-11-18T15:45:52.030 回答
1

我不会告诉你这是一个坏主意,因为听起来你已经被告知得够多了。哦,对不起,我想我刚刚做了......无论如何,这里是如何做到的:

using System.Runtime.Serialization;

    C myInstance = FormatterServices.GetUninitializedObject(typeof(C));
    myInstance.M();

上面的“GetUninitializedObject”方法返回一个对象的实例,而不调用任何实例 ctor(显然任何静态类型 ctor 仍将运行)。然后,您可以根据需要戳实例字段或简单地调用方法。

再次,作为一个整体的坏主意;)

于 2009-11-18T16:39:32.740 回答