سؤال

لا أفهم عندما يجب استخدام معلمة الإخراج، وأنا شخصيا التفاف النتيجة في نوع جديد إذا كنت بحاجة إلى إرجاع أكثر من نوع واحد، أجد أنه أسهل كثيرا في العمل مع خارج.

لقد رأيت طريقة مثل هذا،

   public void Do(int arg1, int arg2, out int result)

هل هناك أي حالات منطقية في الواقع؟

ماذا عن TryParse, ، لماذا لا ترجع ParseResult يكتب؟ أو في الإطار الأحدث إرجاع نوعا فارغا؟

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

المحلول

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

public bool DoSomething(int arg1, out string result);

في هذه الحالة، يمكن أن تشير العائد إذا نجحت الوظيفة ويتم تخزين النتيجة في المعلمة خارج. من المسلم به أن هذا المثال مفاهما لأنه يمكنك تصميم طريقة حيث تقوم الوظيفة ببساطة بإرجاع string, ، لكن انت فهمت الفكرة.

العيب هو أنه يجب عليك إعلان متغير محلي لاستخدامها:

string result;
if (DoSomething(5, out result))
    UpdateWithResult(result);

بدلاً من:

UpdateWithResult(DoSomething(5));

ومع ذلك، قد لا يكون ذلك عيبا، فإنه يعتمد على التصميم الذي ستذهب إليه. في حالة DateTime، يتم توفير كلا الوسيلة (تحليل و TryParse).

نصائح أخرى

كذلك مع معظم الأشياء التي يعتمدها. دعونا نلقي نظرة على الخيارات

  • يمكنك العودة كل ما تريد كقيمة إرجاع الوظيفة
  • إذا كنت ترغب في إرجاع قيم متعددة أو الوظيفة لديها بالفعل قيمة إرجاع، فيمكنك استخدامها إما بالفطار أو إنشاء نوع مركب جديد يكشف كل هذه القيم كخصائص

في حالة TryParse، باستخدام عمارة خارجية فعالة - لا تضطر إلى إنشاء نوع جديد سيكون 16 مليار من النفقات العامة (على أجهزة 32 مليار) أو تكبد تكلفة Perf التي يتم جمعها من القمامة التي تم جمعها. يمكن استدعاء Tryparse من داخل حلقة على سبيل المثال - حتى خارج القوام الحكم هنا.
بالنسبة للوظائف التي لن يتم استدعاؤها ضمن حلقة (أي أداء ليس مصدر قلق كبير)، قد يكون إرجاع كائن مركب واحد "نظيفا" (شخصي للناهي). الآن مع أنواع مجهولة والكتابة الديناميكية، قد تصبح أسهل.

ملحوظة:

  1. out تتمتع المعارف ببعض القواعد التي تحتاج إلى اتباعها، فسيضمن المحول البرمجي أن الوظيفة تقوم بتهيئة القيمة قبل خروجها. لذلك يجب أن يقوم TryParse بتعيين التعامل مع بعض القيمة حتى إذا فشلت تحليل العملية
  2. يعد نمط Tryxxx مثالا جيدا عند استخدام Params - Int32.trienperse تم تقديم صعيد كوز اشتكى من ضرب Perf من استثناءات التقاطات لمعرفة ما إذا كانت تحليل فشلت. كما أن الشيء الأكثر احتمالا التي ستفعلها في حالة تحليلها نجحت، والحصول على القيمة المحيطة بها - باستخدام مخاوف خارجية تعني أنك لا تضطر إلى جعل طريقة أخرى استدعاء لتحليل

أعتقد أنه مفيد للحالات التي تحتاج فيها إلى إرجاع كل من المنطقي والقيمة، مثل tryparse، ولكن سيكون من الرائع أن يسمح المترجم بشيء مثل هذا:

bool isValid = int.TryParse("100", out int result = 0);

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

public void Do(int arg1, int arg2, out int result)

لا يجعل من المنطقي استخدام معلمة خارجية، لأنك تعود فقط إلى قيمة واحدة فقط، ويمكن استخدام هذه الطريقة أفضل إذا قمت بإزالة المعلمة خارج ووضع قيمة إرجاع INT:

public int Do(int arg1, int arg2)

هناك بعض الأشياء الجيدة حول المعلمات خارج:

  1. تعتبر معلمات الإخراج مبدئيا غير موضحة.
    • كل معلمة خارجية يجب يتم تحديدها بالتأكيد قبل إرجاع الطريقة، لن يترجم الكود الخاص بك إذا فاتتك مهمة.

في الختام، أنا أحاول أساسا استخدام المعالم في بلدي API الخاص. لتجنب إنشاء أنواع منفصلة لفافة قيم عودة متعددة، وعلى واجهة برمجة التطبيقات الخاصة بي، استخدمها فقط على الأساليب التي تتطابق مع نمط tryparse.

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

يبدو إنشاء نوع فقط لقيم العودة مؤلمة قليلا بالنسبة لي :-) أولا، سأضطر أولا إلى إنشاء نوع لإرجاع القيمة، في طريقة الاتصال، قمت بتعيين القيمة من النوع الذي تم إرجاعه إلى المتغير الفعلي الذي يحتاجه.

المعلمات خارج هي simipler لاستخدامها.

نعم، فإنه لا معنى له. خذ هذا على سبيل المثال.

String strNum = "-1";
Int32 outNum;

if (Int32.TryParse(strNum, out outNum)) {
    // success
}
else {
    // fail
}

ماذا يمكنك العودة إذا فشلت العملية في وظيفة طبيعية مع قيمة الإرجاع؟ من المؤكد أنك لا تستطيع العودة -1 لتمثيل فشل، لأنه بعد ذلك لن يكون هناك تمايز بين قيمة الفشل والإرجاع والقيمة الفعلية التي كانت تحللها لتبدأ. هذا هو السبب في أننا نعود قيمة منطقية لمعرفة ما إذا كانت قد نجحت، وإذا حدث ذلك، لدينا قيمة "العودة" الخاصة بنا تم تعيينها بالفعل بالفعل.

إنه يزعجني أنني لا أستطيع المرور ب NULL إلى المعلمة خارج وظائف TryParse.

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

إذا قمت دائما بإنشاء نوع، فيمكنك الانتهاء من الكثير من الفوضى في طلبك.

كما قال هنا، حالة الاستخدام النموذجي واحد TrySomething الطريقة التي تريد إرجاع bool كمؤشر للنجاح ثم القيمة الفعلية. أجد أيضا أن نظافة بعض الشيء في بيان if - جميع الخيارات الثلاثة لها نفس الموقع تقريبا على أي حال.

int myoutvalue;
if(int.TryParse("213",out myoutvalue){
    DoSomethingWith(myoutvalue);
}

vs.

ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
    DoSomethingWith(myoutvalue.Value);
}

vs.

int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
    DoSomethingWith(myoutvalue.Value);
}

أما بالنسبة ل "لماذا لا ترجع نوعا لا يغلب": LeParse موجود منذ Framework 1.x، في حين جاءت أنواع Nullable مع 2.0 (كما يحتاجون إلى الأردن). فلماذا كسر التوافق غير المعقول أو البدء في إدخال التناقضات بين tryparse في بعض الأنواع؟ يمكنك دائما كتابة طريقة التمديد الخاصة بك إلى الوظائف المكررة الموجودة بالفعل (انظر اريك لترز على موضوع غير مرتبط يتضمن بعض التفكير وراء القيام / عدم القيام بالأشياء)

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

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

StatusInfo a, b, c;

Initialize(out a);
Validate(a, out b);
Process(b, out c);

ضد.

StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);

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

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