2017-02-27 13 views
1

実際に変数が格納されている場所のようなインタビューで最近尋ねられました。 私は値の型の変数がStackに格納されていると答えています。Reference型の変数はヒープに格納されていますが、インタビュアーは私にprogram.Pleaseでリアルタイムのシナリオを教えてもらうように頼んだり、参考type.Ifに格納することができ、プログラムでの例を与えることができ、それは、これらの変数がどこにあるか私に教えてください非常に有用であるか、私はこれらが値の種類と参照の種類リアルタイムメモリの割り当て

class Program 
{ 
    int i = 5; 
    bool a; 
    string str = "Stack Overflow"; 
    object obj = "object"; 
    string employeeName; 
    int employeeCode; 

    public int Add(int x,int y) 
    { 
     float a = 7.0F; 
     return x + y; 
    } 


    static void Main(string[] args) 
    { 
     Program obj = new Program(); 
     obj.employeeCode = 1000; 
     obj.employeeName = "John"; 
     int result = obj.Add(10, 15); 
    } 
} 

を格納し得ているVSで確認することができます任意のツールをお知らせします何らかの理由で格納されています。値の型と参照の型の両方の例を表示してください

+0

'値型の変数はスタック上に保存されており、参照型の変数はHeap'に保存されている年齢だしました言語。この混乱する話題に関するいくつかの大きな洞察については、[this](http://jonskeet.uk/csharp/memory.html)の記事をご覧ください。 – RBT

+0

非常に密接に関連した投稿[ここ](https://stackoverflow.com/q/3542083/465053)。 – RBT

答えて

3

以下は、フードの中で起こっていることの概要です。私が提供できる最良の例は、スタックとヒープ表現を持つ一連の図形です。

まず、兵士と士官の2つのクラスがあるとしましょう。役員は兵士を擁護する。また、method1の内部にいくつかのロジックがあります。 method1の実行が開始されると、スタックとヒープの状態があります。スタックには前回の実行から何かがありますが、今は重要ではありません。ヒープにはクラス定義があります。法1の開始時に

Initial state

1)2つの変数がスタック年齢にプッシュされますので、私たちは宣言文のカップルを持っています。今はを指すには何もしていますし、年齢 == 0

enter image description here

2)S =新役員()ステートメントは、ヒープ内の新しいオブジェクトを作成し、このオブジェクトのアドレスは今

enter image description here

3に割り当てられている)のは、そのSを想像してみましょうoldier.Lookup(name)はSoldierクラスの静的メソッドです。たとえば、Databaseにクエリを実行し、新しいOfficerオブジェクトを生成します。その結果、ポインタは新しいオブジェクトを指し、前のオブジェクトはガベージコレクションの候補です。

Static method call

4)次の文は、単に値の割り当てです。 年齢は31になりました(31はGetSoldierAge()操作の結果です)。

Simple assignment

5)s.CurrentStatusReport()は、いくつかの副作用(印刷報告書)を持っていると私たちの記憶には影響を与えませんので、我々はそれを無視します。次のステートメントはsendOutForTraining(年齢、s)のメソッドの呼び出しであり、ここではたくさんの楽しみがあります:)

バリュー/リファレンス。興味深い部分。

6)実行sendOutForTraining(年齢、Sになる)次の処理が行われますsendOutForTraining

  • ポインタ)が目的を返す(スタックにプッシュされます。

  • 変数が作成され、スタックにプッシュされます。 年齢の値は、すぐににコピーされます。

  • 変数sldrが作成され、スタックにプッシュされます。 SからポインタがSLDRにコピーされ、現在SSLDRが同じオブジェクトを指しています。 sendOutForTraining

    7)+ = 2がスタックで計算されて記憶されるの結果を入力

entering sendOutForTraining

。ご覧のとおり、年齢年齢:は異なる変数で、異なる値が含まれています。

a assignment

8)さて、sldr.age =。この操作の結果は、sldrが指している共有オブジェクトに影響することは明らかです。したがって、年齢はこのメソッドの外で33に等しくなければなりません。

age changing

9)別の割り当て。 sldr = new Soldier();結果は新しいオブジェクトで、そのアドレスはsldrに保存されています。 メソッドの外部からの変数は、それについてはわかりません。絶対に気にしないでください。

New object created

10)最後の文は、単にSLDRアドレスの下にオブジェクトのインスタンスフィールドを変更します。

Change age of another object

11)方法の実行は終了するジョブが実行されたときに、すべてのアーチファクトを洗浄しなければなりません。未使用の変数は破棄され、オブジェクトはガベージコレクトされます。私たちが見ることができるように

Cleaning artifacts

12)、sedOutForTrainingはマークを生きてきました。これは、C#での最大の神話の一つである - 役員のオブジェクトのインスタンス変数は、それが= 33

The final state