2017-12-25 19 views
1

たとえば、あるクラスにvoidというメソッドが1つあります。C#でのこれらの2つのメソッド呼び出しの違いは何ですか?

これが私のクラスである:

class MyClassTest 
{ 
    public void Print() 
    { 
     Console.WriteLine("Hello"); 
    } 
} 

私はクラスに新しく、少し混乱しています、これらの二つのメソッド呼び出しの間に違いはありますか?ここで

は私の主な方法は、あなたが構築されたオブジェクトへの参照を保持し、後でそれをさらにいくつかの操作を実行したい場合に、これを行うことになるでしょう下回る場合

static void Main(string[] args) 
{ 
    //first call 
    MyClassTest ms = new MyClassTest(); 
    ms.Print(); 

    //second call 
    new MyClassTest().Print(); 
} 
+3

要するに、違いはありません。 – JohnyL

+0

@JohnyLどのようにすればいいですか? –

+0

@RonJeremy、同じインスタンスの複数のメソッドを呼び出すとします.2番目の呼び出しがまだオプションになりますか?それはすべて同じインスタンスを再利用することです。 –

答えて

5

です。

MyClassTest ms = new MyClassTest(); 
ms.Print(); 

場合には、あなたがだけあなたはもはや建設後に構築されたオブジェクトを気にしませんが、メソッドPrintを呼び出すことで、単に興味を持っているとき、これを行うしたいと思うの下に、一方。

new MyClassTest().Print(); 

これら2つのシナリオの間の微妙な違いは オブジェクトが参照されている場合には、それが最も可能性が高いもはや上述の第2の例、すなわち参照されるオブジェクトよりも後に破棄されますさらに操作を実行することですGC(ガベージコレクタ)は参照がなく、したがってそれを取り除くことを決定します。

+3

2回目を頻繁にやっていると、間違ったことをする可能性が高くなります。 inspectを気にしない場合は、静的メソッドを使用してください –

+0

どちらの場合も、オブジェクトは、呼び出し直後に収集できます(変数が長くなってその値を検査できるようにするデバッガ下で実行する場合を除く)。 – Evk

+0

@Evkまあまあ、一般的に参照を持つオブジェクトは、参照を持たないものよりも後でガベージコレクションされる可能性が高く、オブジェクトがガベージコレクションされる時間は_non-deterministic_です。 –

0

あなたの2つの呼び出しは同じ意味操作をc#で実行します。最初の呼び出しではmsという変数が作成されます。これはコード内で再度使用することを意味します。後にms.Print()と呼んでください。

あなたの2番目の呼び出しは、任意の変数を宣言していない、これはあなたの目的はあなたのコードの中で一度だけのブランドの新しいMyClassTestインスタンス上Printメソッドを呼び出すために正確であることを意味し、あなたが作成したインスタンスを気にしません。

サイドノート:リリースモードでコンパイルすると、C#コンパイラはコンパクトで変数の使用量を減らすため、2つのコールは同じようにコンパイルされ、2番目のコールと同じになります。

+0

いくつかのプロパティに 'ms'変数(obj)を使用すると、そのリリースモードについて素敵な説明をありがとうございます。 –

+1

あなたは大歓迎です。追加の "もの"に 'ms'を使うと、コンパイルされたコードが変更されます。しかし、正確な出力は、現在の状況で推定するのが困難な多くの要因に依存します。 – pier

2

実際には違いはありません。プログラムでさらにMyTestClassを参照する必要がある場合は、最初のケースを使用します。 2番目のケースはfire-and-forgetとします。 2番目のケースを頻繁に使用する予定の場合は、Printメソッドをstaticとすることをお勧めします。可変保持参照がスタックにロードされたとき

ILコードはWithInstance方法以外に差を示さず(stloc.0ldloc.0 IL命令):

MyClassTest ms = new MyClassTest(); 
ms.Print(); 

Image1

new MyClassTest().Print(); 

Image2

+0

変数を保持する参照がないため、このメソッドの2番目の静的呼び出しがメモリのスペースを節約しますか? –

+0

2番目の方法では、最初にメモリを割り当てます。静的メソッドについては、静的メソッドを持つ静的クラスまたは通常クラスのいずれかを使用する必要があります。 – JohnyL

0

この特定の場合、いいえ。

別のメソッド呼び出しの結果でメソッドを呼び出すときはいつでも、new、プロパティアクセスなどそれはあなたがした場合に似てい

new MyClassTest().Print(); 

:につきとして

var temp = new MyClassTest() 
temp.Print(); 

をので、このケースでは、あなたの二つの例は同じです。

いくつかのバリエーションがあります。

1つは、配列またはフィールドアクセスからアクセスされる値型オブジェクトです。ここでは、アクセスはコピーを作成するのではなく、実際のオブジェクトのアドレスを使用する場合があります。これで逆のことが起こる可能性があります。暗黙的な一時的なローカルの作成と明示的なローカルの削除の代わりに、それは約束されていません。可変値型では、一時的なローカルの有無にかかわらず、これらのケースでは意味的に同じではないことに注意してください(ただし、例に近いケースの場合、オブジェクトがメソッド呼び出しの結果であるref returnからrefへの変数)。

もう1つは、yield -usingまたはasyncの方法の場合です。ここであなたのメソッド内の地元の人々は、上記の "見えない"一時的な地元の人はそうではないが、生産されたオブジェクト(yieldの場合はIEnumerable<T>および/またはIEnumerator<T>asyncの場合はTask)を実装するオブジェクトのフィールドになります。 (コンパイラは、yieldまたはasyncの呼び出しの後に存在しないもののいくつかを取り除く上でより良い仕事をする可能性があります。したがって、現実にはフィールドでなくてもかまいません地元の人々は畑になる)。

したがって、1回の操作で明示的なローカルユーザーが値を取得した方法で直接操作を行う場合とは若干異なりますが、その場合の例は1つではありません。

関連する問題