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

การส่งพารามิเตอร์แบบ Pass by Reference ใน C#

ภาพรวม

Pass by Reference (การส่งอ้างอิง) ใน C# ทำให้เมธอดเข้าถึง ตัวแปรจริง (Argument) โดยตรง ไม่ได้สร้าง Copy ค่า หรือ Copy Reference การเปลี่ยนแปลงพารามิเตอร์ภายในเมธอดจะ ส่งผลต่อตัวแปรต้นฉบับ ทันที

คีย์เวิร์ด: ref

ใช้ ref ทั้งใน Signature เมธอด และตอนเรียกใช้

ตัวอย่างโปรแกรม: Swap แบบ Pass by Reference

using System;

namespace CalculatorApplication
{
    class NumberManipulator
    {
        // ref ใน Signature
        public void Swap(ref int x, ref int y)
        {
            int temp = x;
            x = y;
            y = temp;
        }
        
        static void Main(string[] args)
        {
            NumberManipulator n = new NumberManipulator();
            int a = 100;
            int b = 200;
            
            Console.WriteLine("ก่อน Swap: a={0}, b={1}", a, b);
            
            // ref ตอนเรียกใช้
            n.Swap(ref a, ref b);
            
            Console.WriteLine("หลัง Swap: a={0}, b={1}", a, b);
            Console.ReadLine();
        }
    }
}

ผลลัพธ์

ก่อน Swap: a=100, b=200
หลัง Swap: a=200, b=100

ค่า a, b สลับกันจริง เพราะทำงานบนตัวแปรเดียวกัน

คีย์เวิร์ดที่เกี่ยวข้อง: ref, out, in

คีย์เวิร์ดทิศทางต้อง Initialize ก่อนส่งต้อง Assign ในเมธอดคำอธิบาย
refTwo-way (In/Out)ใช่ไม่อ่าน/เขียนตัวแปรจริง
outOut Onlyไม่ใช่ (บังคับ)สำหรับ Return หลายค่า
inIn Only (Readonly)ใช่ไม่ (Compile Error)Pass by Reference แบบอ่านอย่างเดียว

ตัวอย่าง out Parameter (Return หลายค่า)

public bool TryParseInt(string input, out int result)
{
    return int.TryParse(input, out result);
}

// ใช้งาน
if (TryParseInt("123", out int value))
    Console.WriteLine("Parsed: " + value); // 123

ตัวอย่าง in Parameter (Readonly Reference)

// ส่ง Struct ใหญ่ๆ แบบไม่ Copy และไม่ให้แก้ไข
public void ProcessLargeStruct(in BigStruct data)
{
    // data.X = 10; // Compile Error! Cannot assign to 'in' parameter
    Console.WriteLine(data.X); // อ่านได้
}

// ใช้งาน
BigStruct s = new BigStruct { X = 42 };
ProcessLargeStruct(in s); // หรือ ProcessLargeStruct(s) ก็ได้ (in implicit)

แผนภาพหน่วยความจำ (ref)

Main Stack Frame:
┌─────────┐
│ a: 100  │ ◄───┐
└─────────┘     │  Same Memory Location
                ▼
Swap Stack Frame:
┌─────────┐
│ x (ref) │ ─── Points to 'a'
├─────────┤
│ y (ref) │ ─── Points to 'b'
└─────────┘

ข้อสังเกตสำคัญ

  • ref ต้อง Initialize ก่อนส่ง (Definite Assignment)
  • out ไม่ต้อง Initialize ก่อน แต่บังคับ Assign ในเมธอดทุก Path
  • in เพิ่มใน C# 7.2 - เหมาะสำหรับ Struct ใหญ่ (Performance) และบ่งชี้ Intent (Read-only)
  • Properties ไม่สามารถส่งเป็น ref/out ได้ (เพราะไม่ใช่ Variable) - ต้อง Copy ไป Variable ก่อน
  • Async Methods ไม่รองรับ ref/out Parameters
  • Iterator Methods (yield return) ไม่รองรับ ref/out

เมื่อไหร่ควรใช้ ref/out/in

  • ref: Swap, 修改參數, 高性能 Struct 傳遞
  • out: TryParse Pattern, 多返回值
  • in: 大型 Struct 傳遞 (避免 Copy), 唯讀參數