ماذا المرجع ، فال والخروج يعني على طريقة المعلمات ؟

StackOverflow https://stackoverflow.com/questions/13060

  •  08-06-2019
  •  | 
  •  

سؤال

أنا أبحث عن واضحة وموجزة ودقيقة الإجابة.

بطبيعة الحال الإجابة الفعلية ، على الرغم من وصلات إلى تفسيرات جيدة موضع ترحيب.

هذا ينطبق أيضا على VB.Net لكن الكلمات مختلفة - ByRef و ByVal.

هل كانت مفيدة؟

المحلول

بشكل افتراضي (في C#), تمرير كائن إلى وظيفة في الواقع يمر نسخة من الإشارة إلى هذا الكائن.تغيير المعلمة نفسها فقط بتغيير قيمة المعلمة ، وليس المتغير الذي تم تحديده.

void Test1(string param)
{
    param = "new value";
}

string s1 = "initial value";
Test1(s1);
// s1 == "initial value"

باستخدام out أو ref يمر إشارة إلى المتغير المحدد في استدعاء الدالة.أي تغييرات تطرأ على قيمة out أو ref المعلمة سيتم تمريرها إلى المتصل.

سواء out و ref تتصرف بشكل مماثل باستثناء فارق واحد بسيط: ref معلمات مطلوبة initialised قبل الدعوة ، في حين out المعلمات يمكن uninitialised.قبل التمديد ، ref المعلمات مضمونة initialised في بداية طريقة ، في حين out المعلمات معاملة uninitialised.

void Test2(ref string param)
{
    param = "new value";
}

void Test3(out string param)
{
    // Use of param here will not compile
    param = "another value";
}

string s2 = "initial value";
string s3;
Test2(ref s2);
// s2 == "new value"
// Test2(ref s3); // Passing ref s3 will not compile
Test3(out s2);
// s2 == "another value"
Test3(out s3);
// s3 == "another value"

تحرير:كما dp يشير الفرق بين out و ref هو فقط ينفذ من قبل برنامج التحويل البرمجي C#, ليس CLR.بقدر ما أعرف, VB لا يوجد لديه أي ما يعادل out وتنفذ ref (كما ByRef) فقط ، مطابقة دعم CLR.

نصائح أخرى

واحدة ملاحظة إضافية عن الحكم مقابلمن:الفرق بين الاثنين هو القسري من قبل برنامج التحويل البرمجي C#.CLR لا يميز بين بين و المرجع.وهذا يعني أنه لا يمكن أن يكون لديك طريقتين التواقيع تختلف فقط من قبل أو المرجع

void foo(int value) {}

// Only one of the following would be allowed

// valid to overload with ref
void foo(ref int value) {}

// OR with out
void foo(out int value) {}

out يعني أن المعلمة سوف يكون initialised من طريقة:

int result; //not initialised

if( int.TryParse( "123", out result ) )
   //result is now 123
else
   //if TryParse failed result has still be 
   // initialised to its default value (0)

ref وسوف القوة الكامنة الإشارة إلى أن مرت:

void ChangeMyClass1( MyClass input ) {
   input.MyProperty = "changed by 1";
   input = null;
   //can't see input anymore ... 
   // I've only nulled my local scope's reference
}

void ChangeMyClass2( ref MyClass input ) {
   input.MyProperty = "changed by 2";
   input = null;
   //the passed reference is now null too.
}

MyClass tester = new MyClass { MyProperty = "initial value" };

ChangeMyClass1( tester );
// now tester.MyProperty is "changed by 1"

ChangeMyClass2( ref tester );
// now tester is null

واحدة من بلدي الأسئلة في ستاكوفيرفلوو يعالج هذا الموضوع أيضا.
فإنه يعالج عن "تمر بها المرجعية" و "تمر قيمة" في أنواع مختلفة من اللغات ، c# يتم تضمين لذا ربما يمكنك أن تجد بعض المعلومات الإضافية هناك أيضا.

في الأساس أنه يأتي إلى أسفل إلى:

  • ref:المعلمة مع المرجع الكلمة سوف تكون مرت بالرجوع
  • من:المعلمة مع أصل الكلمة سوف تكون يعامل معلمة الإخراج

ولكن هذا في الحقيقة أبسط الإجابة, كما هو قليلا أكثر تعقيدا مما هو مذكور هنا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top