10

私は主にC++で作業しており、現在は新しい仕事でC#を使用しています。ここで、「ref」キーワードとc#値と参照型について読んだ後も、まだ混乱が見られます。

これらをメソッドに渡す場合、これらを理解している限り、これらは類似したC++スタイルになります。

値のタイプ:

public void CSharpFunc(value)

public void CPlusplusFunc(value)

参照型:

public void CSharpFunc(reference)

public void CPlusPlusFunc(&reference)

'ref'/ポインタ

public void CSharpFunc(ref bar)

public void CPlusPlus(*bar)

これは正しいアナロジーですか?

4

3 に答える 3

12

これは正しいアナロジーですか?

他の答えが言っていることにもかかわらず、いいえ。refC ++の意味は、実際にはタイプによって異なります。値型の場合、評価は正しい(または十分に近い)。参照型の場合、より適切な例えは、ポインターへの参照です。

public void CPlusPlus(type*& bar)

重要なのは、渡される参照を変更refできるということです。C++では、ポインターを渡すだけでは変更できません。

void f(type* bar) {
    bar = new_address;
}

type* x;
f(x);

このコードは、呼び出し元の値を変更しませんx。一方、barとして合格した場合は、値変更されます。それが何をするかです。type*&ref

さらに、C#での参照は、C ++での参照とはまったく異なり、C ++でのポインターに非常に似ています(参照が参照するオブジェクトを変更できるという点で)。

于 2012-08-13T13:39:02.927 に答える
3

「参照型」と「」の例を入れ替えた方が正確です(ただし、まったく同じではありません)。ref

C#では、参照型は、型のインスタンスへの参照を介して常に内部的にアクセスされる型です。これらをC++の意味での「ポインタ」として使用するのが最も簡単です。メモリを割り当て、コンストラクタを実行して、必要なオブジェクトを間接的に参照する値を取得します。ここでのC#とC ++の違いは、C#では、これは変数ではなく、のプロパティであるということです。タイプは常に参照型または常に値型。この効果の1つは、参照型を使用するために特別なことをする必要がないことです(マネージC#コードには「逆参照」演算子はありません)。コンパイラーは、参照型の変数アクセスが間接化されていると想定します。C ++でも、同じ型( vs. )->の値変数と参照変数の両方を持つことができるため、演算子を使用する必要があります。object xobject *x

refキーワードは、参照によってパラメーターを渡すために使用されます。これらのパラメーターは、値型(のようなint)または参照型のいずれかです。キーワードの実装は、ref最終的にはアドレス型/ポインタ型の操作ですが(&C ++の場合とまったく同じです)、ref(および)マネージド参照outと呼ばれる特別な型のオブジェクトを生成します。これは、参照型とは異なります。値型への管理された参照を持つことができます。これは、C ++の動作とほぼ同じです。anは、基本的に変数へのアクセスにポインター間接参照を使用している場合でも、とは異なる特殊なタイプの「intへの参照」です。同様に、C#では、を使用できます。これは事実上。になります。int&int *ref Objectobject *&

于 2012-08-13T13:39:37.650 に答える
1

はい、おおむね正しいです (s/*/*& で、100% 正解です)。@weston が述べたように、outよく知っておくべき追加のキーワードです。あなたができる唯一のかわいいことはref、refではない関数をオーバーロードすることです。

class Person {
   string Name { get; set; }
   string Address { get; set; }
   int age { get; set; }
}

public void UpdateName(Person p)
{
   if (p == null) 
   {
      return;
   }

   p.Name = "Tom";
}

public void UpdateName(ref Person p)
{
   if (p == null)
   {
      p = new Person();
   }

   p.Name = "Tom";
}

明らかに役に立ちませんが、いくつかの興味深い機会 (および悪い設計) を提供します。 out同じオーバーロード機能を提供しません。

1 対 1 が必要な場合は、いつでも でコードをブロックできますunsafe

于 2012-08-13T13:34:01.540 に答える