سؤال

ما هي الأشياء التي يجب مراعاتها عند الاختيار بين ByRef وByVal.

أنا أفهم الفرق بين الاثنين ولكني لا أفهم تمامًا ما إذا كان ByRef يحفظ الموارد أو إذا كنا بحاجة إلى القلق بشأن ذلك في بيئة .Net.

كيف يمكنك الاختيار بين الاثنين إذا كانت الوظيفة غير مهمة في موقف ما؟

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

المحلول

وهناك الكثير من المعلومات الخاطئة حول حول هذا الموضوع. الشيء الرئيسي هو أن تفهم الفرق بين قيمة وأنواع المرجعية، و تمريرة من حيث القيمة وتمرير بالرجوع .

وأردت دائما تقريبا لتمرير من حيث القيمة. يمر بالرجوع دائما تقريبا "أريد أن أعود أكثر من نتيجة واحدة، وليس فقط عن طريق إضافة أشياء إلى قائمة التي يتم تمريرها في." والمثال الكلاسيكي على طريقة استخدام تمرير كل إشارة غير Int32.TryParse حيث قيمة الإرجاع هو نجاح / فشل، وقيمة تحليل و"عاد" من قبل المعلمة خارج.

نصائح أخرى

والافتراضي هو byValue لجميع أنواع، ولكن من المهم أن نفهم ما تعنيه الخيارين ل"نوع مرجع" (فئة) بدلا من نوع قيمة. (البنيات).

لنوع مرجع، إذا قمت بتعريف متغير نوع مرجع في الأسلوب، هذا المتغير هو موقع الذاكرة في إطار كومة من طريقة. انها ليست على الكومة. عند تهيئة هذا المتغير (باستخدام جديدة أو مصنع، أيا كان)، ثم قمت بإنشائها كائن الفعلي على كومة، ويتم تخزين عنوان هذا الكائن في متغير إشارة أعلن في وسائل الخاص بك كومة الإطار.

عند تمرير نوع إشارة إلى طريقة أخرى BYVAL، كنت تقوم بإنشاء نسخة من عنوان المخزنة في الدعوة أساليب كومة وتمرير نسخة من تلك القيمة (عنوان المؤشر) إلى استدعاء الأسلوب، حيث يتم تخزينها في فتحة ذاكرة جديدة في تسمى كومة الأساليب. داخل طريقة تسمى، ونقاط متغيرة المستنسخة جديدة مباشرة إلى نفس الكائن في كومة. وذلك باستخدام أنه يمكن تغيير خصائص الكائن نفسه. ولكن لا يمكنك تغيير أي كومة الاعتراض المتغير إشارة الأصلي (على أساليب الدعوة كومة) نقطة ل. إذا، في طريقة تسمى أكتب

  myVar = new object();

والمتغير الأصلي في طريقة الدعوة لن يتغير للإشارة إلى كائن جديد.

إذا مررت نوع مرجع الأساسية ByRef، OTOH، وأنا تمرير مؤشر إلى متغير أعلن في أساليب الدعوة كومة (الذي يحتوي على مؤشر إلى الكائن على كومة) ولذلك هو مؤشر إلى مؤشر إلى كائن . ويشير إلى موقع الذاكرة على استدعاء أساليب كومة، مما يشير إلى كائن على الكومة.
وحتى الآن، إذا قمت بتغيير قيمة المتغير في طريقة تسمى، من خلال وضع لكائن جديد ()، على النحو الوارد أعلاه، لأنه هو "refereence" لالمتغير في طريقة الدعوة، وأنا في الواقع تغيير الكائن الذي المتغير في أسلوب الدعوة يشير إلى. حتى بعد يسمى إرجاع الأسلوب، المتغير في أسلوب الدعوة لن يتم الإشارة إلى نفس الكائن الأصلي على الكومة.

يجب أن يكون

والأساسية ByVal بك "الافتراضي". استخدامه إلا إذا كان لديك سبب محدد لاستخدام الأساسية ByRef

وتمرير الأساسية ByVal الكائن في صافي لا يجعل نسخة من الكائن ولا تستهلك المزيد من الموارد الأساسية ByRef ثم، لا يزال تمرير مؤشر من خلال وظيفة. وقت التشغيل يضمن فقط أنه لا يمكنك تعديل المؤشر في الدالة وإرجاع قيمة مختلفة لذلك. لا يزال بإمكانك إجراء تغييرات على القيم داخل الكائن وسترى هذه التغييرات خارج الدالة. هذا هو السبب الأساسية ByRef هو يستخدم نادرا ما. وهناك حاجة فقط عندما تريد وظيفة لتغيير الكائن الفعلي الذي يعود. وبالتالي معلمة إخراج.

استخدم "الأساسية ByRef" فقط إذا كانت المعلمة "إخراج" المعلمة. على خلاف ذلك استخدام "الأساسية ByVal". باستخدام "الأساسية ByRef" على المعلمات التي صراحة لا ينبغي إرجاع القيم أمر خطير ويمكن أن يسهل توليد الخلل.

وأنا أزعم أن الأساسية ByRef يجب ألا تستخدم أبدا - أنها عادة سيئة. وأود أن تطبيق ذلك حتى لقضيته استخدام نموذجية من السماح لوظيفة لإرجاع القيم المتعددة (عن طريق الأساسية ByRef المعلمات). سيكون من الأفضل لوظيفة للعودة استجابة منظمة التي تضم تلك القيم عودة متعددة. انها أكثر وضوحا وأكثر وضوحا إذا الدالة بإرجاع فقط القيم عبر بيان عودتها.

يؤدي وضع علامة على وسيطات معينة على أنها ByRef إلى إظهار مستخدم وظيفتك أن عامل المخصصة لتلك الوسيطة **سيتم تعديلها.****

إذا كنت تستخدم ByRef بالنسبة لجميع الوسيطات، لن تكون هناك طريقة لمعرفة المتغيرات التي تم تعديلها بواسطة الدالة، وأيها يتم قراءتها فقط. (بصرف النظر عن النظرة الخاطفة داخل مصدر الوظيفة!)

وفقًا لمايكروسوفت، يمكن أن يؤثر اختيار ByVal أو ByRef على أداء القيم الكبيرة بدرجة كافية (انظر تمرير الوسيطات حسب القيمة والمرجع (Visual Basic)):

أداء.على الرغم من أن آلية المرور يمكن أن تؤثر على أداء الكود الخاص بك ، فإن الفرق عادة ما يكون غير مهم.استثناء واحد لهذا هو نوع القيمة الذي تم تمريره Byval.في هذه الحالة ، يقوم Visual Basic بنسخ محتويات البيانات بأكملها من الوسيطة.لذلك، لقيمة كبيرة اكتب مثل الهيكل، يمكن أن يكون أكثر كفاءة لتمريره byref.

[تم اضافة التأكيدات].

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

هناك الكثير من الالتباس سأحاول تبسيطه.لديك في الأساس 4 خيارات:

  1. تمرير نوع القيمة byVal
  2. تمرير نوع القيمة بواسطةRef
  3. تمرير كائن بواسطةVal
  4. تمرير كائن بواسطةRef

بعض الناس يقولون أنه يجب عليك أبداً استخدم بواسطةالمرجع.وفي حين أنها صحيحة من الناحية الفنية، هناك شيء واحد مؤكد.يجب أبداً استخدم الكلمة أبداً.إذا كنت تقوم بتصميم نظام من الصفر، فيجب تجنب byRef بأي ثمن.استخدامه يكشف عن خلل في التصميم.ومع ذلك، فإن العمل على نظام موجود قد لا يوفر قدرًا كبيرًا من المرونة لتنفيذ تصميم جيد.في بعض الأحيان يجب عليك تقديم التنازلات، أي.باستخدام بواسطةالمرجع.على سبيل المثال، إذا كان بإمكانك إجراء الإصلاح خلال يومين باستخدام byRef، فقد يكون ذلك أفضل من إعادة اختراع العجلة واستغرق أسبوعًا للحصول على نفس الإصلاح فقط لتجنب استخدام byRef.

ملخص:

  1. استخدام byVal على نوع القيمة:يمرر قيمة إلى دالة.هذه هي الطريقة المفضلة لتصميم وظائف.
  2. استخدام byRef على نوع القيمة:مفيد لإرجاع أكثر من قيمة واحدة من دالة.إذا كنت تقوم بإنشاء وظيفة تحتاج إلى إرجاع أكثر من قيمة إلى نظام حالي ، فيمكن أن يكون ذلك أفضل من إنشاء كائن (وإعداد الخصائص ، والتخلص) فقط لوظيفة واحدة.
  3. استخدام byVal على كائن:يمرر مؤشر كائن إلى دالة.يمكن للوظيفة تعديل الكائن.
  4. استخدام byRef على كائن:يمرر مؤشرًا إلى مؤشر كائن إلى دالة.يسمح بتغيير الكائن الذي يشير إليه المتصل.يمكن أن يتسبب ذلك في صعوبة العثور على الأخطاء ولا يمكنني التفكير في أي سبب وجيه لاستخدامه.لا يعني أنه لا يوجد واحد ، ولكن إذا كان هناك عدد قليل ومتباعدة.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top