Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在不调用构造函数的情况下调用实例方法_C#_Constructor_Methods_Instance - Fatal编程技术网

C# 在不调用构造函数的情况下调用实例方法

C# 在不调用构造函数的情况下调用实例方法,c#,constructor,methods,instance,C#,Constructor,Methods,Instance,假设我有以下课程,我不允许更改: public class C { public C() { CreateSideEffects(); } public void M() { DoSomethingUseful(); } } 我必须在不调用构造函数的情况下调用M。有可能吗?没有。因为C.M是一个实例方法,所以需要创建一个实例,这意味着调用构造函数 C是你们团队拥有的一个类吗?如果是这样,但你奉命别管它,你最好游说: 这些副作用需要重构和消除 C.M方法功能移到了另一个类中,或者

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

public class C
{
    public C() { CreateSideEffects(); }
    public void M() { DoSomethingUseful(); }
}
我必须在不调用构造函数的情况下调用M。有可能吗?

没有。因为C.M是一个实例方法,所以需要创建一个实例,这意味着调用构造函数

C是你们团队拥有的一个类吗?如果是这样,但你奉命别管它,你最好游说:

这些副作用需要重构和消除 C.M方法功能移到了另一个类中,或者是静态的。 如果C来自第三方,您将遇到麻烦,并且可能必须在您自己的方法中复制C.M的功能。

否。因为C.M是一个实例方法,您需要创建一个实例,这意味着调用构造函数

C是你们团队拥有的一个类吗?如果是这样,但你奉命别管它,你最好游说:

这些副作用需要重构和消除 C.M方法功能移到了另一个类中,或者是静态的。
如果C来自第三方,您将遇到麻烦,并且可能必须在您自己的方法中复制C.M的功能。

为了调用实例方法,您需要一个实例!而且,出于充分的理由,获得一个的唯一方法是通过构造函数。否则,整个对象可能处于不确定或无用状态,因为尚未进行初始化。因此,即使存在某种黑客行为,这也不是一个好的选择


在没有实例的情况下,您只能调用静态方法。

为了调用实例方法,您需要一个实例!而且,出于充分的理由,获得一个的唯一方法是通过构造函数。否则,整个对象可能处于不确定或无用状态,因为尚未进行初始化。因此,即使存在某种黑客行为,这也不是一个好的选择

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

是的,您可以

不用说,这是一个糟糕的设计,但你已经知道,不能改变它。如果必须,可以尝试部分模拟该类

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

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

C c = Mockito.mock(C);
Mockito.doCallRealMethod().when(c).M();
// If M() isn't a void method
// when(c.M()).thenCallRealMethod();
c.M();
但是,在这种情况下,M不能依赖于构造函数中设置的任何状态

有关部分模拟的更多信息,请查看此。然而,模拟主要用于测试。

是的,你可以

不用说,这是一个糟糕的设计,但你已经知道,不能改变它。如果必须,可以尝试部分模拟该类

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

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

C c = Mockito.mock(C);
Mockito.doCallRealMethod().when(c).M();
// If M() isn't a void method
// when(c.M()).thenCallRealMethod();
c.M();
但是,在这种情况下,M不能依赖于构造函数中设置的任何状态

有关部分模拟的更多信息,请查看此。然而,模拟主要用于测试。

即使这不是一个好主意,是的,我们可以; 有

即使这不是一个好主意,是的,我们可以; 有


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

using System.Runtime.Serialization;

    C myInstance = FormatterServices.GetUninitializedObject(typeof(C));
    myInstance.M();
上面的“GetUninitializedObject”方法返回对象的实例,而不调用任何实例构造函数。显然,任何静态类型构造函数仍将运行。然后,您可以根据需要插入实例字段,或者只调用方法


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

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

using System.Runtime.Serialization;

    C myInstance = FormatterServices.GetUninitializedObject(typeof(C));
    myInstance.M();
上面的“GetUninitializedObject”方法返回对象的实例,而不调用任何实例构造函数。显然,任何静态类型构造函数仍将运行。然后,您可以根据需要插入实例字段,或者只调用方法


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

这个问题相当于问,我想给我的猫取个名字,而没有猫。我该怎么做?@programminghero+1代表lolz。尽管如此,还是让他放心吧。这可能是因为这是一个第三方类,他真正想要C.M的功能,但他无法控制它需要考虑的事项:如果一个方法修改了实例状态,那么它就是一个有状态的方法,并且应该是一个实例方法。如果一个方法不修改实例状态,那么它是一个无状态方法,应该是一个静态方法。因此,实例方法是两件事中的一件,要么是有状态的方法并需要正确实例化实例,要么是编写得非常糟糕的类。考虑到这个问题是一个假设性问题,可能是一个访谈问题,我不明白我们为什么要给他讲课。rd@johnnyg:

我见过很多很多写得很糟糕的课程,我无法改变,不得不使用它们。与流行的观点相反,并不是每个人都具备80js-90js的编程技能,其中100js是Jon Skeet,为他们的产品提供API或库的人会编写无状态方法并使其成为非静态的。这个问题相当于问,我想给我的猫起名,而没有猫。我该怎么做?@programminghero+1代表lolz。尽管如此,还是让他放心吧。这可能是因为这是一个第三方类,他真正想要C.M的功能,但他无法控制它需要考虑的事项:如果一个方法修改了实例状态,那么它就是一个有状态的方法,并且应该是一个实例方法。如果一个方法不修改实例状态,那么它是一个无状态方法,应该是一个静态方法。因此,实例方法是两件事中的一件,要么是有状态的方法并需要正确实例化实例,要么是编写得非常糟糕的类。考虑到这个问题是一个假设性问题,可能是一个访谈问题,我不明白我们为什么要给他讲课。rd@johnnyg:我见过很多,很多写得很差的课程,我无法改变,不得不使用。与流行的观点相反,并非所有人都具备80js-90js的编程技能,其中100js是Jon Skeet,为其产品提供API或库的人编写无状态方法并使其非静态。移动副作用+1。构造函数不应该做任何工作,除了成员赋值。繁重的工作应该始终委托给post-ctor方法,以避免在实例化时出现异常。@johnnyg嗯,不一定总是这样。如果您的对象是通过IoC加载的,那么您将无法对它们进行初始化,因为接口可能没有初始化方法,并且您无法保证即使有,也会调用它。如果类在调用方法等时进行惰性初始化,这会有所帮助,但实际上在ctor中做一些工作并不是那么糟糕。问题是,它确实会导致实际的适当副作用,从而在其他地方造成麻烦。移动副作用+1。构造函数不应该做任何工作,除了成员赋值。繁重的工作应该始终委托给post-ctor方法,以避免在实例化时出现异常。@johnnyg嗯,不一定总是这样。如果您的对象是通过IoC加载的,那么您将无法对它们进行初始化,因为接口可能没有初始化方法,并且您无法保证即使有,也会调用它。如果类在调用方法等时进行惰性初始化,这会有所帮助,但实际上在ctor中做一些工作并不是那么糟糕。问题是,它是否确实会造成实际的适当副作用,从而在其他地方造成麻烦。哇,这有点像过河拆桥,否则你会因为是一个邪恶的天才而得到+1@尼尔,问题是这是否可能。与所说的相反,这是可能的。这是一个不同的问题,关于它是否好。是的,我知道,但这是一条线,关于某件事是否可能,与是否应该做。如果有人问你是否有可能从二楼的窗户上摔下来,你可以说是的,但你还是强烈建议他们不要这样做。你可以考虑一个善意的谎言,告诉他们不:我不知道这是可能的,并在我的回答中说了同样的话。从所有的意图和目的来看,这是不可能的。好吧,这取决于上下文。e、 如果他是一名测试人员,并且他不想承担在构造函数中发生的数据库连接的成本。为了测试其他与数据库无关的方法,通常在那里创建一个mock。这并不少见,尤其是测试人员不能更改代码,特别是如果它是遗留代码。哇,这是一个相当多的交叉流,否则你会因为是一个邪恶的天才而得到+1@尼尔,问题是这是否可能。与所说的相反,这是可能的。这是一个不同的问题,关于它是否好。是的,我知道,但这是一条线,关于某件事是否可能,与是否应该做。如果有人问你是否有可能从二楼的窗户上摔下来,你可以说是的,但你还是强烈建议他们不要这样做。你可以考虑一个善意的谎言,告诉他们不:我不知道这是可能的,并在我的回答中说了同样的话。从所有的意图和目的来看,这是不可能的。好吧,这取决于上下文。e、 如果他是一名测试人员,并且他不想承担在构造函数中发生的数据库连接的成本。为了测试其他与数据库无关的方法,通常在那里创建一个mock。这并不少见,尤其是测试人员不能更改代码,特别是如果它是遗留代码。