تمرير معلمات من نوع مرجع (دليل البرمجية لـ #C)

لا يحتوي المتغير من النوع مرجع على البيانات الخاصة به مباشرة; يحتوي على مرجع إلى البيانات. عند تمرير معلمة من نوع مرجع بالقيمة من الممكن تغيير بيانات المشار إليها بواسطة المرجع مثل قيمة عضو بالفئة. لكن لا يمكنك تغيير قيمة المرجع نفسه; أي، لا يمكنك استخدام نفس المرجع لتخصيص ذاكرة لفئة جديدة وجعلها تستمر خارج الكتلة. لفعل هذا مرر المعلمة باستخدام الكلمات الأساسية ref أو out. للتبسيط, فإن الأمثلة التالية تستخدم ref.

مثال

يوضح المثال التالي تمرير معلمة من نوع مرجع arr بالقيمة إلى الأسلوب Change. لأن المعلمة عبارة عن مرجع لـ arrفمن الممكن تغيير قيم عناصر الصفيف. مع ذلك، محاولة إعادة تعيين المعلمة إلى موقع ذاكرة مختلف يعمل فقط داخل الأسلوب ولا يؤثر على المتغير الأصلي arr.

class PassingRefByVal 
{
    static void Change(int[] pArray)
    {
        pArray[0] = 888;  // This change affects the original element.
        pArray = new int[5] {-3, -1, -2, -3, -4};   // This change is local.
        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
    }

    static void Main() 
    {
        int[] arr = {1, 4, 5};
        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);

        Change(arr);
        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
    }
}
/* Output:
    Inside Main, before calling the method, the first element is: 1
    Inside the method, the first element is: -3
    Inside Main, after calling the method, the first element is: 888
*/

في المثال السابق يتم تمرير الصفيف arr وهو من نوع مرجع إلى الأسلوب بدون المعلمة ref. في مثل هذه الحالة، يتم تمرير نسخة من المرجع الذي يشير إلى arr إلى الأسلوب. تُظهر المخرجات أنه يمكن للأسلوب أن يقوم بتغيير محتويات عنصر صفيف، في هذه الحالة من 1 إلى 888. مع ذلك، تخصيص جزء جديد من الذاكرة باستخدام عامل التشغيل new داخل الأسلوب Change يجعل المتغير pArray يشير إلى صفيف جديد. ومن ثم فإن أية تغييرات بعد ذلك لا تؤثر على الصفيف الأصلي arr الذي تم إنشاؤه داخل Main. في الحقيقة، تم إنشاء صفيفين في هذا المثال، واحد داخل Main و الآخر داخل أسلوب Change.

هذا المثال هو نفس المثال السابق، باستثناء ما يتعلق باستخدام الكلمة الأساسية ref في عنوان الأسلوب وفي الاتصال. أي تغيير يحدث في الأسلوب سيؤثر على المتغيرات الأصلية في البرنامج المستدعي.

class PassingRefByRef 
{
    static void Change(ref int[] pArray)
    {
        // Both of the following changes will affect the original variables:
        pArray[0] = 888;
        pArray = new int[5] {-3, -1, -2, -3, -4};
        System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
    }

    static void Main() 
    {
        int[] arr = {1, 4, 5};
        System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);

        Change(ref arr);
        System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);
    }
}
/* Output:
    Inside Main, before calling the method, the first element is: 1
    Inside the method, the first element is: -3
    Inside Main, after calling the method, the first element is: -3
*/

كل التغييرات التى تحدث داخل الأسلوب تؤثر على الصفيف الأصلي في Main. في الحقيقة، تم إعادة تخصيص الصفيف الأصلي باستخدام عامل التشغيل new. لذلك، بعد استدعاء الأسلوب Change، أي مرجع لـ arr يشير إلى الصفيف ذو الخمسة عناصر الذي تم إنشاؤه في الأسلوب Change.

مبادلة السلاسل عبارة عن مثال جيد لتمرير معلمات من نوع مرجع بالمرجع. في المثال، يتم تهيئة سلسلتين str1 و str2 في Main وتم تمريرهما إلى الأسلوب SwapStrings كمعلمات معدّله بواسطة الكلمة الأساسية ref. يتم تبديل السلسلتين داخل الأسلوب وداخل Main أيضاً.

 class SwappingStrings
 {
     static void SwapStrings(ref string s1, ref string s2)
     // The string parameter is passed by reference.
     // Any changes on parameters will affect the original variables.
     {
         string temp = s1;
         s1 = s2;
         s2 = temp;
         System.Console.WriteLine("Inside the method: {0} {1}", s1, s2);
     }

     static void Main()
     {
         string str1 = "John";
         string str2 = "Smith";
         System.Console.WriteLine("Inside Main, before swapping: {0} {1}", str1, str2);

         SwapStrings(ref str1, ref str2);   // Passing strings by reference
         System.Console.WriteLine("Inside Main, after swapping: {0} {1}", str1, str2);
     }
 }
 /* Output:
     Inside Main, before swapping: John Smith
     Inside the method: Smith John
     Inside Main, after swapping: Smith John
*/

في هذا المثال، نحتاج أن نمرر المعلمات بالمرجع لنؤثر على المتغيرات في البرنامج المستدعي. إذا قمت بإزالة الكلمة الأساسية ref من عنوان الأسلوب واتصال الأسلوب، لا تتم أية تغييرات في البرنامج المتصل.

للحصول على معلومات أكثر حول السلاسل، راجع السلسلة.

راجع أيضًا:

المرجع

تمرير المعلمات (دليل البرمجة لـ #C)

تمرير الصفائف باستخدام ref و out ( ارشادات برمجة C# )

ref (مرجع #C)

مرجع أنواع (C# مرجع)

المبادئ

دليل البرمجة لـ #C