スタック
  stack格納するメモリのブロックであるlocal variablesとparameters。関数が開始および終了すると、スタックは論理的に拡大および縮小します。
次の方法を検討してください。
public static int Factorial (int x)
{
    if (x == 0) 
    {
        return 1;
    }
    return x * Factorial (x - 1);
}
このメソッドは再帰的です。つまり、それ自体を呼び出します。メソッドが入力されるたびに、新しいintがスタックに割り当てられ、メソッドが終了するたびに、intの割り当てが解除されます。
ヒープ
  
  - ヒープは、objects(つまりreference-type instances)が存在するメモリのブロックです。新しいオブジェクトが作成されるたびに、そのオブジェクトはヒープに割り当てられ、そのオブジェクトへの参照が返されます。プログラムの実行中、新しいオブジェクトが作成されると、ヒープがいっぱいになり始めます。ランタイムには、ヒープからオブジェクトの割り当てを定期的に解除するガベージコレクターがあるため、プログラムは実行されませんOut Of Memory。オブジェクトは、それ自体が参照されていない場合はすぐに割り当て解除の対象になりますalive。
- ヒープも格納しstatic fieldsます。ヒープに割り当てられたオブジェクト(ガベージコレクションが発生する可能性がある)とは異なり、these live until the application domain is torn down。
次の方法を検討してください。
using System;
using System.Text;
class Test
{
    public static void Main()
    {
        StringBuilder ref1 = new StringBuilder ("object1");
        Console.WriteLine (ref1);
        
        StringBuilder ref2 = new StringBuilder ("object2");
        StringBuilder ref3 = ref2;
        
        Console.WriteLine (ref3); 
    }
}    
上記の例では、変数ref1によって参照されるStringBuilderオブジェクトを作成することから始め、次にその内容を書き出します。そのStringBuilderオブジェクトは、その後何も使用しないため、すぐにガベージコレクションの対象になります。次に、変数ref2によって参照される別のStringBuilderを作成し、その参照をref3にコピーします。それ以降はref2は使用されませんが、ref3は同じStringBuilderオブジェクトを存続させ、ref3の使用が終了するまでコレクションの対象にならないようにします。
  値型インスタンス(およびオブジェクト参照)は、変数が宣言されている場所ならどこにでも存在します。インスタンスがクラスタイプ内のフィールドとして、または配列要素として宣言されている場合、そのインスタンスはヒープ上に存在します。