Page cover

Ref keyword

ขวัญปีใหม่ พึ่งไชย 650710531

ในที่นี้เราจะมาพูดถึง ref keyword ในภาษา C# เราจะใช้ตัวแปร ref เพื่อส่งค่าไปยังเมธอดหรือรับค่าจากเมธอด ซึ่งหมายความว่า เมธอดสามารถเปลี่ยนแปลงค่าของพารามิเตอร์ได้โดยตรงเมื่อแก้ไขค่าที่มีการจองพื้นที่อยู่ก่อนแล้ว เมื่อใช้ ref การแก้ไขค่าภายในเมธอดจะส่งผลต่อค่าจริงในหน่วยความจำทันที ทำให้ไม่ต้องคัดลอกข้อมูล ช่วยให้โค้ดทำงานเร็วขึ้น โดยเฉพาะกับข้อมูลขนาดใหญ่

📄 การใช้งาน ref

  1. การประกาศ

    • ต้องประกาศตัวแปร ref ไว้ด้านหน้าพารามิเตอร์ของเมธอด

    • ต้องประกาศตัวแปร refไว้ด้านหน้าตัวแปรที่ประกาศไว้ตอนการเรียกใช้เมธอด

  2. การเปลี่ยนแปลงค่า

    • ถ้าส่งพารามิเตอร์เข้าไปในเมธอดด้วย ref เมธอดนั้นจะสามารถเปลี่ยนแปลงค่าของตัวแปรต้นฉบับได้โดยตรง

💻 การใช้ ref

สามารถใช้ ref ได้ในกรณีต่อไปนี้:

1. ส่งอาร์กิวเมนต์ไปยังเมธอดโดยการอ้างอิงถึงตัวแปรนั้น

(To pass an argument to a method by its reference) ซึ่งการใช้ ref จะอนุญาตให้เมธอดนั้นแก้ไขค่าของตัวแปรต้นฉบับได้

using System;

namespace TomAndJerryGame
{
    class Program
    {
        static void Main(string[] args)
        {
            //กำหนดคะแนนเริ่มต้น
            int tomScore = 50;
            int jerryScore = 45;

            Console.WriteLine($"Initial scores: Tom = {tomScore}, Jerry = {jerryScore}");

            ModifyScores(ref tomScore, ref jerryScore);

            Console.WriteLine($"Modified scores: Tom = {tomScore}, Jerry = {jerryScore}");
        }
        
   // ฟังก์ชัน ModifyScores สำหรับอัปเดตคะแนน โดยรับออบเจ็กต์ Character แบบอ้างอิง (ref)
        public static void ModifyScores(ref int tomScore, ref int jerryScore)
        {
            tomScore += 15;
            jerryScore += 10;
        }
    }
}

Output

การส่งค่าหลายค่าด้วย ref

แม้ว่าโดยปกติแล้วเมธอดจะสามารถส่งคืนค่าได้เพียงค่าเดียว แต่ถ้าเราใช้ ref เราสามารถส่งกลับค่าหลายค่าได้ โดยการส่งตัวแปรหลายตัวเข้าไปในเมธอดเป็นพารามิเตอร์แบบ ref


2. กำหนดลายเซ็นของเมธอดให้ส่งคืนอ้างอิงของตัวแปร

(To define a method signature to return a reference of the variable) การทำให้เมธอดสามารถส่งคืนตำแหน่งในหน่วยความจำของตัวแปรได้แทนที่จะส่งคืนแค่ค่าของตัวแปรนั้น

Output


3. ประกาศโครงสร้างเป็น ref struct

(To declare a struct as a ref struct) การประกาศ ref struct จะช่วยให้มั่นใจว่าโครงสร้างนี้จะถูกเก็บใน stack เท่านั้น การที่โครงสร้างอยู่ใน stack จะช่วยลดภาระในการจัดการหน่วยความจำและทำให้การเข้าถึงข้อมูลรวดเร็วขึ้น

Output


4. การอ้างอิงในท้องถิ่น

(As local reference) การสร้างตัวแปรที่เชื่อมโยงกับตัวแปรอื่นภายในพื้นที่เดียวกัน ถ้าเราเปลี่ยนแปลงค่าของตัวแปรที่เชื่อมโยง ตัวแปรเดิมก็จะเปลี่ยนไปด้วย

Output


⚠️ ข้อควรระวัง

  • ต้องกำหนดค่าเริ่มต้น: ตัวแปรที่ส่งเข้าไปโดยใช้ ref ต้องมีค่าเริ่มต้นก่อน ไม่งั้นจะเกิดปัญหา

  • ต้องใช้คำสำคัญในทั้งสองที่: เมื่อเราประกาศพารามิเตอร์ในเมธอดก็ต้องใช้ ref และเมื่อเราจะเรียกใช้เมธอดก็ต้องใส่ ref ด้วยเช่นกัน

การใช้ ref ใน C# ช่วยให้เราสามารถส่งพารามิเตอร์โดยอ้างอิง พร้อมเปลี่ยนแปลงค่าตัวแปรต้นฉบับได้ เพิ่มประสิทธิภาพในการจัดการข้อมูลขนาดใหญ่ได้เร็วขึ้น


🆚 เปรียบเทียบกับภาษา Java/C/Python

การใช้คีย์เวิร์ด ref ใน C# เป็นการส่งผ่านค่าผ่านการอ้างอิง (pass by reference) ซึ่งมีความแตกต่างจากการส่งผ่านค่าปกติ (pass by value) ที่เป็นการส่งค่าจากตัวแปรไปยังฟังก์ชันหรือเมธอดอื่น ๆ ในรูปแบบที่ค่าตัวแปรนั้นถูกส่งตรงตามที่อยู่ในหน่วยความจำ ไม่ใช่ค่าสำเนาของตัวแปรนั้น ๆ

การทำงานของ ref ใน C#

  1. ใน C# การใช้ ref จำเป็นต้องใช้ทั้งในตอนที่เรียกใช้และตอนที่ประกาศฟังก์ชัน เพื่อบอกว่าอาร์กิวเมนต์ถูกส่งผ่านโดยการอ้างอิง

  2. เมื่อส่งตัวแปรไปยังฟังก์ชันด้วย ref การเปลี่ยนแปลงในตัวแปรภายในฟังก์ชันจะสะท้อนผลกลับมายังตัวแปรที่ส่งไป

Output

การเปรียบเทียบกับภาษาอื่น ๆ

1. Java

เมื่อเราส่งผ่านการอ้างอิง (pass by reference) หมายความว่า เราส่ง "ตัวจริง" ของออบเจ็กต์เข้าไปในฟังก์ชัน ไม่ได้ส่งสำเนา เมื่อฟังก์ชันทำอะไรกับออบเจ็กต์นั้น เช่น เปลี่ยนค่าในออบเจ็กต์ ค่าที่ถูกเปลี่ยนจะมีผลกับตัวจริงเลย เพราะทั้งตัวที่ส่งเข้าไปและตัวที่ใช้ในฟังก์ชันต่างก็ชี้ไปที่ออบเจ็กต์เดียวกัน ไม่ได้แยกกันทำงาน

ดังนั้น ถ้าเราส่งออบเจ็กต์ไปฟังก์ชันแล้วไปเปลี่ยนค่าอะไรในนั้น ค่าในตัวจริงก็จะเปลี่ยนตามไปด้วย

เพราะฉะนั้น ใน Java ไม่มีคีย์เวิร์ดเฉพาะแบบ ref เพราะ Java ใช้การส่งค่าตัวแปรแบบ pass-by-value ในทุกกรณี แต่หากส่งออบเจ็กต์จะเป็นการส่งที่อยู่ของออบเจ็กต์นั้น (pass-by-reference) คล้ายกับการใช้งาน ref ใน C#

Output

2. C

ในภาษา C สามารถทำสิ่งที่คล้ายกับ ref ได้ด้วยการใช้ pointer (ตัวชี้) ซึ่งเป็นการส่งตัวแปรผ่านการอ้างอิงที่ตรงไปตรงมา

pointer (ตัวชี้)

ตัวชี้ถูกกำหนดให้เป็นชนิดข้อมูลที่ได้รับมาซึ่งสามารถจัดเก็บที่อยู่ของตัวแปร C อื่นๆ หรือตำแหน่งหน่วยความจำ เราสามารถเข้าถึงและจัดการข้อมูลที่จัดเก็บในตำแหน่งหน่วยความจำนั้นได้โดยใช้ตัวชี้

Output

3. Python

Python ส่งผ่านค่าตัวแปรแบบ pass-by-object-reference ซึ่งมีลักษณะคล้ายกับการ pass-by-reference ใน C# เมื่อทำการส่งออบเจ็กต์ (เช่น list หรือ dictionary) แต่หากส่งค่าที่เป็น immutable (เช่น integer, string) จะคล้ายกับ pass-by-value

รูปแบบการส่งอาร์กิวเมนต์ของ Python ไม่ใช่ “Pass by Value” หรือ “Pass by Reference” แต่เป็น “Pass by Object Reference”

Output

สรุป

  • C#: ใช้ ref สำหรับ pass-by-reference ทั้งการประกาศและการเรียกฟังก์ชัน

  • Java: ไม่มี ref โดยตรง แต่การส่งออบเจ็กต์มีลักษณะคล้ายการ pass-by-reference

  • C: ใช้ pointer เพื่อส่งผ่านค่าผ่านการอ้างอิง

  • Python: ใช้การส่งผ่านออบเจ็กต์ (pass-by-object-reference) ขึ้นอยู่กับชนิดข้อมูล

การใช้ ref ทำให้ควบคุมการส่งผ่านค่าผ่านการอ้างอิงได้ชัดเจนขึ้นใน C#


🎞️Presentation

presentation ref keyword

📚 แหล่งที่มา

1. GeeksforGeeks. (July 16, 2021). Ref in C#.

Retrieved from https://www.geeksforgeeks.org/ref-in-c-sharp/

2. Microsoft. (January 8, 2024). Ref keyword.

Retrieved from https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref

3. TutorialsTeacher. (January 7, 2020). Ref keyword.

Retrieved from https://www.tutorialsteacher.com/articles/ref-keyword

4. Microsoft. (July 30, 2024). Ref struct.

Retrieved fromhttps://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/ref-struct

  1. GeeksforGeeks. (October 17, 2022). Different Ways to Achieve Pass By Reference in Java.

Retrieved from https://www.geeksforgeeks.org/different-ways-to-achieve-pass-by-reference-in-java/

  1. GeeksforGeeks. (July 24, 2024). C Pointers.

Retrieved from https://www.geeksforgeeks.org/c-pointers/

  1. GeeksforGeeks. (August 9, 2024). Pass by reference vs value in Python.

Retrieved from https://www.geeksforgeeks.org/pass-by-reference-vs-value-in-python/

Last updated