استخدام الاستثناءات غير المعالجة بدلا من أن يحتوي على()?

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

  •  08-06-2019
  •  | 
  •  

سؤال

تخيل كائن كنت تعمل مع مجموعة من الكائنات الأخرى المرتبطة بها ، على سبيل المثال ، تسيطر المجموعة على WinForm.تريد التحقق من كائن معين في جمع ، ولكن جمع لا Contains() الأسلوب.هناك عدة طرق للتعامل مع هذا.

  • تنفيذ الخاص بك Contains() الطريقة حلقات من خلال جميع العناصر الموجودة في المجموعة لمعرفة ما إذا كان واحد منهم هو ما كنت أبحث عنه.يبدو أن هذا هو "أفضل الممارسات" النهج.
  • كنت مؤخرا قد جاء عبر بعض التعليمات البرمجية حيث بدلا من حلقة ، كانت هناك محاولة الوصول إلى الكائن داخل المحاولة البيان على النحو التالي:
try  
{  
    Object aObject = myCollection[myObject];  
}  
catch(Exception e)  
{  
    //if this is thrown, then the object doesn't exist in the collection
}

سؤالي هو كيف الفقراء من ممارسات البرمجة هل تعتبر الخيار الثاني ولماذا ؟ كيف هو أداء ذلك بالمقارنة مع حلقة من خلال جمع ؟

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

المحلول

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

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

على سبيل المثال استثناء يمكن أن يلقى لأنه كائن لا وجود له في المجموعة ، أو لأن جمع نفسه باطل أو لأنك لا يمكن أن يلقي myCollect[myObject] إلى aObject.

كل هذه الاستثناءات سوف تحصل على التعامل معها بنفس الطريقة التي قد لا تكون نيتك.

هذه هي بضع مقالات عن متى وأين هو usally تعتبر مقبولة إلى رمي الاستثناءات:

أنا لا سيما مثل هذا اقتباس من المقالة الثانية:

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

نصائح أخرى

وكقاعدة عامة من الإبهام تجنب استخدام الاستثناءات من أجل السيطرة على تدفق إلا في ظروف من شأنها أن تؤدي إلى الاستثناء هي "استثنائية" -- على سبيل المثال ، نادرة للغاية!

إذا كان هذا هو شيء سوف يحدث عادة بانتظام فإنه بالتأكيد لا ينبغي التعامل معها باعتبارها استثناء.

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

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

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

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

يجب أن نفكر أكثر كم أحبه...غريزتى هو ليس كثيرا...

تحرير:ريان فوكس التعليقات على حالة استثنائية مثالية ، أنا أتفق

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

إذا المفهرس O(1) (أو حتى O(log(n))...أو أي شيء أسرع من O(n)) ، ثم حاول/catch الحل يكون أسرع بالطبع.

أيضا, أنا على افتراض المفهرس هو رمي استثناء ، إذا كان إرجاع null, هل يمكن بطبيعة الحال مجرد التحقق من باطل وعدم استخدام try/catch.

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

النهائي الفكر في هذه الأيام معظم مجموعات هل قد يحتوي على طريقة بالفعل.لذلك أعتقد أن معظم هذه مسألة غير.

الاستثناءات يجب أن تكون استثنائية.

شيء مثل 'جمع مفقود لأن قاعدة البيانات سقط من تحته' استثنائية

شيء مثل 'هذا هو السلوك الطبيعي عن القاموس.

المحددة الخاصة بك مثال winforms التحكم في المجموعة ، Controls مكان الإقامة ContainsKey طريقة, وهو ما كنت من المفترض أن استخدام.

لا يوجد ContainsValue لأنه عند التعامل مع القواميس/hashtables لا يوجد طريقة سريعة قصيرة من بالتكرار من خلال مجموعة كاملة من فحص إذا كان هناك شيء موجود, لذلك كنت حقا بالإحباط من ذلك.

أما لماذا الاستثناءات يجب أن تكون استثنائية ، عن الأشياء 2

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

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

نلقي نظرة على هذا بلوق وظيفة من Krzystof: http://blogs.msdn.com/kcwalina/archive/2008/07/17/ExceptionalError.aspx

الاستثناءات يجب أن تستخدم للتواصل الشروط خطأ, ولكن لا ينبغي أن تستخدم منطق السيطرة (خاصة عندما تكون هناك الآن أبسط الطرق لتحديد الشرط ، مثل تحتوي على).

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

وهذا الأخير هو حل مقبول.على الرغم من أنني بالتأكيد القبض على الاستثناء (ElementNotFound?) أن جمع يلقي في هذه الحالة.

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

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