C#
 Computer >> コンピューター >  >> プログラミング >> C#

C#でのref、out、およびinキーワードの使用法は何ですか?


C#では、ほとんどのメソッドは、メソッドに提供する必要のあるデータを定義する0個以上のパラメーターを持つことができます。メソッドを呼び出すコードはすべて、データ(引数と呼ばれる)をメソッドに渡す必要があります。メソッドはその入力をパラメーターとして宣言し、引数の形式でコードを呼び出すことによって提供されます。

たとえば、次のメソッドとそれに続くメソッド呼び出しについて考えてみます。

static void Greet(string greeting){
   Console.WriteLine(greeting);
}
...
Greet("Hello");

上記の例では、greetingはGreet()メソッドのパラメーターであり、「Hello」はメソッドに渡される引数です。

メソッドを呼び出して引数を渡すと、値が渡されます。つまり、メソッドに渡されたときに値のコピーが作成されます。メソッド内の引数に加えられた変更は、元の変数には反映されません。

using System;
int number = 8;
Increase(number);
Console.WriteLine(number); // prints 8
static void Increase(int num){
   num = num + 1;
   Console.WriteLine(num); // prints 9
}

オブジェクトなどの参照型変数を渡す場合でも、C#は参照をコピーします 変数は実際のオブジェクトではなく参照を保持するため、値によって。したがって、参照変数のコピーが渡されても、両方ともメモリ内の同じオブジェクトを参照します。したがって、メソッド内の変数によってオブジェクトに加えられた変更は、メソッド外の変数に表示されます。

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(john);
Console.WriteLine(john.Salary); // prints 60000
static void Promote(User u){
   u.Salary += 10000;
   Console.WriteLine(u.Salary); // prints 60000
}

ただし、メソッド内で変数の値自体を変更した場合、実際のオブジェクトではなくコピーのみが変更されたため、その変更はメソッド外には反映されません。たとえば、メソッド内で引数をnullに割り当てることができ、実際の変数は変更されません。

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(john);
Console.WriteLine(john.Salary); // prints 50000
static void Promote(User u){
   u = null;
}
を出力します

C#では、メソッドのパラメーターを制御できる3つの異なる修飾子キーワードを使用できます。

ref修飾子

C#では、 refを使用して参照によりパラメーターを渡すことができます。 修飾子。渡される変数が参照型に属しているか値型に属しているかは関係ありません。パラメータと引数の両方が同じメモリ位置を参照します。

次の例では、引数uをnullに設定すると、john変数もnullになり、null参照例外が発生します。

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
Promote(ref john);
Console.WriteLine(john.Salary); // throws System.NullReferenceException
static void Promote(ref User u){
   u = null;
}

ref修飾子を付けて渡された引数は、渡される前に初期化する必要があります。

out修飾子

を除いて、ref修飾子に似ています。
  • 関数に入る前に引数を初期化する必要はありません

  • 引数は、関数から出る前に初期化(割り当て)する必要があります。

以下の例では、Hire関数は、out修飾子を介して渡された新しいユーザーオブジェクトを初期化します。変数が変数であることに注意してください。johnは、Hireメソッドを呼び出すときにオンザフライで宣言されます。

using System;
Hire(out User john);
Console.WriteLine(john.Salary); // prints 50000
static void Hire(out User u){
   u = new User{
      Name = "John",
      Salary = 50000
   };
}
を出力します

refのように 修飾子、 outでマークされた変数 修飾子は参照によって渡されます。

多くの場合、アウト 変数は、次のように関数から複数の戻り値を取得するために使用されます-

using System;
var john = new User{
   Name = "John",
   Salary = 50000
};
bool shouldPromote = Raise(john.Salary, out double hike);
Console.WriteLine(shouldPromote); // True
Console.WriteLine($"Hike Amount = {hike}"); // prints 5000
static bool Raise(int salary, out double hike){
   hike = salary * 0.1;
   return hike < 7000;
}

in修飾子

refに似ています およびアウト inを受け入れるメソッドを除くパラメータ 引数の値は引数を変更できません。試行すると、C#コンパイラはコンパイル時エラーを生成します。

in パラメータは、コンパイラが大きな値型のメモリをパラメータ変数にコピーするのを防ぎ、同時にオブジェクトが誤って変更されるのを防ぎます。これにより、大きな値型をメソッドに渡すときに非常に便利になります。

var point = new Coord();
Verify(point);
static void Verify(in Coord c){
   // error: Cannot assign to variable 'in Coord' because it is a readonly variable
   c = new Coord();
}
struct Coord{
   public int X;
   public int Y;
}

using System;
class Program{
   static void Main(){
      int number = 8;
      Increase(number);
      Console.WriteLine(number); // prints 8
      var john = new User { Name = "John", Salary = 50000 };
      Promote(john);
      Console.WriteLine(john.Salary); // prints 60000
      Leave(john);
      Console.WriteLine(john.Salary); // prints 60000

      LeaveByRef(ref john);
      Console.WriteLine(john?.Salary); // prints nothing

      User dave;
      Hire(out dave);
      Console.WriteLine(dave.Salary); // prints 50000
   }
   static void Increase(int num){
      num = num + 1;
      Console.WriteLine(num); // prints 9
   }
   static void Promote(User u){
      u.Salary += 10000;
      Console.WriteLine(u.Salary); // prints 60000
   }
   static void Leave(User u){
      u = null;
   }
   static void LeaveByRef(ref User u){
      u = null;
   }
   static void Hire(out User u){
      u = new User{
         Name = "John",
         Salary = 50000
      };  
   }
}
class User{
   public string Name { get; set; }
   public int Salary { get; set; }
}

出力

9
8
60000
60000
60000
50000

  1. C#のrefパラメーターとoutパラメーターの違いは何ですか?

    参照パラメータ 参照パラメータは、変数のメモリ位置への参照です。値パラメーターとは異なり、参照によってパラメーターを渡す場合、これらのパラメーターの新しい保管場所は作成されません。 refキーワードを使用して、参照パラメーターを宣言できます。以下は例です- 例 using System; namespace CalculatorApplication {    class NumberManipulator {       public void swap(ref int x, ref int y) {     &nb

  2. =+と+=はPythonで何をしますか?

    + =演算子は、object .__ iadd __()関数のシンタックスシュガーです。 Pythonドキュメントから: これらのメソッドは、拡張された算術割り当て(+ =、-=、* =、@ =、/ =、// =、%=、** =、)を実装するために呼び出されます。 =、&=、^ =、| =)。これらのメソッドは、その場で操作を実行し(自己を変更)、結果を返すようにする必要があります(自己である可能性がありますが、そうである必要はありません)。 例 だからあなたが次のようなことをするとき- a = 5 b = 10 a += b print(a) 出力 これにより、出力が得られます- 15