1

変更が許可されていない次のクラスがあるとします。

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

コンストラクターを呼び出さずにMを呼び出さなければなりません。出来ますか?

4

5 に答える 5

8

それが良いアイデアではない場合でも、はい、できます;)FormatterServicesを使用します。GetUninitializedObject

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

いいえC.M()。はインスタンスメソッドであるため、インスタンスを作成する必要があります。つまり、コンストラクターを呼び出す必要があります。

Cあなたのチームが所有するクラスですか?もしそうなら、あなたはそれを放っておくように命令されています、あなたはどちらかのためにロビーするのが良いでしょう:

  1. リファクタリングして削除するこれらの副作用
  2. C.M()メソッド機能は別のクラスに移動するか、静的になりました。

サードパーティ製の場合Cは、問題が発生し、独自C.M()のメソッドでの機能を複製する必要がある場合があります

于 2009-11-18T15:41:28.683 に答える
4

はい、できます!

言うまでもなく、これは悪い設計ですが、あなたはすでにそれを知っており、それを変更することはできません。必要に応じて、クラスを部分的にモックすることを試みることができます。

編集:私の例ではC#ではなくJavaを使用していることに気づきました。ただし、@ 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()、コンストラクターで設定された状態に依存することはできません。

部分的なモックの詳細については、このFAQの質問を確認してください。ただし、モックは主にテストに使用されます。

于 2009-11-18T15:49:29.307 に答える
1

In order to invoke an instance method, you need an instance! And - for good reasons - the only way to obtain one is via the constructor. Otherwise the whole object may be in an indeterminate or useless state because initializations haven't been made. So even if there was some kind of hack, it would be no good choice at all!

The only kind of class member you can invoke without an instance are static methods.

于 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 に答える