それらはより制限されています。ポインタでは ++ と言えますが、refまたはではできませんout。
編集コメントにいくつかの混乱があるため、明確にする必要があります。ここでのポイントは、ポインターの機能と比較することです。/と同じ操作を実行することはできませんptr++。つまり、メモリ内の隣接する場所をアドレス指定することはできません。と同等のことを実行できるのは事実ですが (ただし、ここでは関係ありません)、それはポインタではなくvaluesの機能と比較することになります。refout(*ptr)++
refスタックは移動されず、out常にスタックのアクティブな領域を参照するように C# が慎重に編成されているため、それらが内部的に単なるポインターであることは間違いありません。
編集もう一度完全に明確にするために(以下の例からまだ明確になっていない場合)、ここでのポイントはref/がスタックを指すoutことしかできないということではありません。スタックを指している場合、言語規則によってダングリング ポインターにならないことが保証されているということです。スタックはメソッド呼び出しの終了に従って情報を破棄するだけであり、リファラーがまだ存在することを確認するチェックを行わないため、この保証が必要です (そしてここで関連性があり、興味深いものです)。
逆に、ref/outが GC ヒープ内のオブジェクトを参照する場合、それらのオブジェクトを必要なだけ存続させることができることは驚くべきことではありません。 GC 圧縮によってオブジェクトを移動してはならない状況をサポートするために、ピニング (以下の例を参照) を提供します。
ref安全でないコードで相互運用を行ったことがある場合は、それがポインターと非常に密接に関連していることに気付くでしょう。たとえば、COM インターフェイスが次のように宣言されているとします。
HRESULT Write(BYTE *pBuffer, UINT size);
相互運用アセンブリは、これを次のように変換します。
void Write(ref byte pBuffer, uint size);
そして、これを実行してそれを呼び出すことができます(COM相互運用機能が配列の固定を処理すると思います):
byte[] b = new byte[1000];
obj.Write(ref b[0], b.Length);
つまり、ref最初のバイトにアクセスすると、そのすべてにアクセスできます。どうやら最初のバイトへのポインタです。