C# ref修飾子, out修飾子
C#のout修飾子、ref修飾子はメソッド使用時に参照を渡すことを目的としている。
いくつか例を示す。
まずはクラスの準備。
class Student { public Student(int Id, string Name, int ScoreJapanese, int ScoreMath, int ScoreEnglish, int ClassNumber) { this.Id = Id; this.Name = Name; this.ScoreJapanese = ScoreJapanese; this.ScoreMath = ScoreMath; this.ScoreEnglish = ScoreEnglish; this.ClassNumber = ClassNumber; } public int Id { get; set; } public string Name { get; set; } public int ScoreJapanese { get; set; } public int ScoreMath { get; set; } public int ScoreEnglish { get; set; } public int ClassNumber { get; set; } }
次にStudent型のの変数を用意し、メソッドに入れてstudentのみ値を変える。
static void Main(string[] args) { var student = new Student(1, "taro", 82, 71, 75, 1); Console.WriteLine(student.Name + ":" + student.Id); classSub(student); Console.WriteLine(student.Name + ":" + student.Id); } public static void classSub(Student student) { student.Id = 2; }
結果はstudentのidは2に変わる。
このようにメソッドに値を渡し、その値を変更した時元の値にも
影響を及ぼすことを参照渡しという。
通常の引数となると、値は変わることはない。
例えば次のような例であればstudentの値は変わらない。
static void Main(string[] args) { var student = new Student(1, "taro", 82, 71, 75, 1); Console.WriteLine(student.Name + ":" + student.Id); classSub2(student); Console.WriteLine(student.Name + ":" + student.Id); } public static void classSub2(Student student) { student = new Student(2, "taro", 82, 71, 75, 1); }
ここで無理やり参照渡しにするのがout修飾子とref修飾子だ。
以下のように使う。
ref修飾子。
static void Main(string[] args) { var student = new Student(1, "taro", 82, 71, 75, 1); Console.WriteLine(student.Name + ":" + student.Id); refSub1(ref student); Console.WriteLine(student.Name + ":" + student.Id); } public static void refSub1(ref Student student) { student = new Student(2, "taro", 82, 71, 75, 1); }
out修飾子
static void Main(string[] args) { var student = new Student(1, "taro", 82, 71, 75, 1); Console.WriteLine(student.Name + ":" + student.Id); outSub1(out student); Console.WriteLine(student.Name + ":" + student.Id); } public static void outSub1(out Student student) { student = new Student(2, "taro", 82, 71, 75, 1); }
違いは大してないような気がするがoutSub1で使ってるoutのついてる引数は
メソッド内で何かしらの値を割り当てられることが必要。
と、ここまで説明してきたけど、正直あまり使わない方がいいような修飾子ではある。
ただし、これを使ってるint.TryParseメソッドやDictionary.TryGetValueメソッドというものがあるので
ある程度は知っておいた方がいいかな、と。
int.TryParseメソッド
int.TryParse("123", out var number); Console.WriteLine(number);
パースとはもちろんキャストのことだがこの場合はstringの123をintに変換する。
さらに第2引数にoutを入れることによってnumberという変数を宣言しつつ123をキャストした結果を格納できる。
キャストに成功すれば、Trueを返し失敗すれば Falseを返す。
Dictionary.TryGetvalueメソッド
dict.Add("田中", "たなか"); Console.WriteLine(dict.TryGetValue("鈴木", out var value)); Console.WriteLine(value); Console.WriteLine(dict.TryGetValue("田中", out var value2)); Console.WriteLine(value2);
C#のDictionary型はkeyが存在しない場合例外が発生してしまう。
なので、TryGetValueによってkeyがあるか確かめつつ値を確認することが重要。
これも上のTryParseメソッドと同様にkeyがあるかを確認し、あった場合はvalueに格納。
さらに値があった場合はTrueを返す。なければFalseを返す。