Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

การใช้งานคีย์เวิร์ด ref, out, และ in ใน C#


ใน C# เมธอดส่วนใหญ่มี Parameters กำหนดข้อมูลที่ต้องส่งเข้า เรียกเมธอดต้องส่ง Arguments เมธอดประกาศ Inputs เป็น Parameters เรียกโค้ดส่ง Arguments

ตัวอย่าง:

static void Greet(string greeting) => Console.WriteLine(greeting);
Greet("Hello"); // "Hello" คือ Argument

Default: Pass by Value (Copy ค่า) การเปลี่ยนแปลงในเมธอดไม่ส่งผลต่อตัวแปรต้นฉบับ

int number = 8;
Increase(number);
Console.WriteLine(number); // 8

static void Increase(int num) { num++; Console.WriteLine(num); // 9 }

Reference Type: Copy Reference (แต่ชี้ Object เดียวกัน) เปลี่ยนข้อมูลใน Object ได้ แต่อย่าเปลี่ยน Reference เอง

var john = new User { Name = "John", Salary = 50000 };
Promote(john);
Console.WriteLine(john.Salary); // 60000

static void Promote(User u) { u.Salary += 10000; }

แต่ถ้าเปลี่ยน Reference (u = null) ตัวแปรจริงไม่เปลี่ยน

ref Modifier

Pass by Reference ด้วย ref ทั้ง Parameter และ Argument ชี้ Memory เดียวกัน (ทั้ง Value และ Reference Type) ตัวอย่าง กำหนด u = null จะทำให้ john เป็น null ด้วย

var john = new User { Name = "John", Salary = 50000 };
Promote(ref john);
Console.WriteLine(john?.Salary); // NullReferenceException

static void Promote(ref User u) { u = null; }

Argument ที่ใช้ ref ต้อง Initialize ก่อนส่ง

out Modifier

คล้าย ref แต่:

  • Argument ไม่ต้อง Initialize ก่อนเข้าฟังก์ชัน
  • Argument ต้อง Initialize (Assign) ก่อนออกจากฟังก์ชัน

ตัวอย่าง Hire สร้าง User ใหม่ผ่าน out:

Hire(out User john);
Console.WriteLine(john.Salary); // 50000

static void Hire(out User u)
{
    u = new User { Name = "John", Salary = 50000 };
}

ใช้ out เพื่อ Return หลายค่า:

bool shouldPromote = Raise(john.Salary, out double hike);
Console.WriteLine(shouldPromote); // True
Console.WriteLine($"Hike = {hike}"); // 5000

static bool Raise(int salary, out double hike)
{
    hike = salary * 0.1;
    return hike < 7000;
}

in Modifier

คล้าย ref/out แต่ Method ไม่สามารถแก้ไข Argument ได้ (Read-Only) Compiler Error หากพยายามแก้ไข เหมาะกับการส่ง Large Value Type เข้าเมธอดโดยไม่ Copy Memory และป้องกันการแก้ไขโดยไม่ตั้งใจ

var point = new Coord();
Verify(point);

static void Verify(in Coord c)
{
    // Error: Cannot assign to readonly variable 'in Coord'
    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); // 8

        var john = new User { Name = "John", Salary = 50000 };
        Promote(john);
        Console.WriteLine(john.Salary); // 60000

        Leave(john);
        Console.WriteLine(john.Salary); // 60000

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

        Hire(out User dave);
        Console.WriteLine(dave.Salary); // 50000
    }

    static void Increase(int num) { num++; Console.WriteLine(num); }
    static void Promote(User u) { u.Salary += 10000; Console.WriteLine(u.Salary); }
    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