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

Ref Locals และ Ref Returns ใน C# 7.0 คืออะไร

Reference Return Value อนุญาตให้ Method คืนค่า Reference ไปยัง Variable แทนที่จะคืนค่า Value

Caller สามารถเลือกได้ว่าจะจัดการ Returned Variable ว่าเป็น Pass by Value หรือ Pass by Reference

Caller สามารถสร้าง Variable ใหม่ที่เป็น Reference ของ Returned Value เรียกว่า Ref Local

ปัญหา: Pass by Value (ปกติ)


class Program {
    public static void Main() {
        var colors = new[] { "blue", "green", "yellow", "orange", "pink" };
        string color = colors[3];  // Copy Value
        color = "Magenta";         // แก้ไข Copy เท่านั้น
        
        Console.WriteLine(string.Join(" ", colors));
        // Output: blue green yellow orange pink (ไม่เปลี่ยน!)
        Console.ReadLine();
    }
}

แก้ด้วย Ref Locals


public static void Main() {
    var colors = new[] { "blue", "green", "yellow", "orange", "pink" };
    
    // ref local - อ้างอิงตรง Element ใน Array
    ref string color = ref colors[3];
    color = "Magenta";  // แก้ไข Element จริงใน Array
    
    Console.WriteLine(string.Join(" ", colors));
    // Output: blue green yellow Magenta pink
    Console.ReadLine();
}

Ref Returns

Method คืนค่า Reference แทน Value

โดยไม่มี Ref Return (Pass by Value)


class Program {
    public static void Main() {
        var colors = new[] { "blue", "green", "yellow", "orange", "pink" };
        string color = GetColor(colors, 3);  // Return Value (Copy)
        color = "Magenta";
        
        Console.WriteLine(string.Join(" ", colors));
        // Output: blue green yellow orange pink
        Console.ReadLine();
    }
    
    public static string GetColor(string[] col, int index) {
        return col[index];  // Return Value
    }
}

ใช้ Ref Return


class Program {
    public static void Main() {
        var colors = new[] { "blue", "green", "yellow", "orange", "pink" };
        
        // รับ Reference จาก Method
        ref string color = ref GetColor(colors, 3);
        color = "Magenta";
        
        Console.WriteLine(string.Join(" ", colors));
        // Output: blue green yellow Magenta pink
        Console.ReadLine();
    }
    
    // Ref Return: คืน Reference ไปยัง Array Element
    public static ref string GetColor(string[] col, int index) {
        return ref col[index];
    }
}

กฎของ Ref Returns

  • Return Type ต้องเป็น ref T
  • Return Statement ต้องเป็น return ref variable;
  • สามารถ Return Reference ได้เฉพาะ:
    • Fields/Array Elements ของ Object ที่มีอยู่แล้ว
    • Ref Parameters ที่รับเข้ามา
    • Ref Locals ใน Method เดียวกัน
  • ไม่สามารถ Return Reference ของ Local Variable (จะ Out of Scope)

ตัวอย่างขั้นสูง: หา Element และแก้ไขในที่เดียว


public class Matrix {
    private double[,] _data;
    
    public Matrix(int rows, int cols) {
        _data = new double[rows, cols];
    }
    
    // Ref Return: เข้าถึง Element โดยตรง
    public ref double this[int row, int col] {
        get => ref _data[row, col];
    }
    
    // หา Max Element และ Return Reference
    public ref double FindMax() {
        int maxRow = 0, maxCol = 0;
        for (int r = 0; r < _data.GetLength(0); r++) {
            for (int c = 0; c < _data.GetLength(1); c++) {
                if (_data[r, c] > _data[maxRow, maxCol]) {
                    maxRow = r; maxCol = c;
                }
            }
        }
        return ref _data[maxRow, maxCol];
    }
}

// Usage
var matrix = new Matrix(3, 3);
// ... fill data ...
ref double max = ref matrix.FindMax();
max = 0; // Reset Max to 0 โดยตรงใน Array

Ref Structs (C# 7.2+) - Stack-only Types


// Ref Struct ต้องอยู่บน Stack เท่านั้น (ไม่มี Heap Allocation)
public ref struct SpanWrapper {
    private Span _span;
    
    public SpanWrapper(Span span) => _span = span;
    
    public ref int this[int index] => ref _span[index];
}

// Usage - ต้องใช้กับ Stack-allocated Memory
Span stackSpan = stackalloc int[100];
var wrapper = new SpanWrapper(stackSpan);
wrapper[0] = 42;

สรุปเมื่อไหร่ใช้ Ref Returns/Locals

  • Performance-critical Code ที่ต้องหลีกเลี่ยง Copy Large Structs
  • Direct Mutation ของ Elements ใน Collections/Arrays
  • Search/Find Methods ที่ต้องการแก้ไข Element ที่เจอทันที
  • High-frequency Trading, Game Engines, Numerical Computing
  • ไม่ควรใช้ ใน General Business Logic (Complexity เพิ่มขึ้น, Safety ลดลง)