سؤال

لقد رأيت السؤال على المحاولة-catch, الذي شخص (بما في ذلك جون السكيت) يقول فارغة قبض كتل تلك فكرة سيئة حقا ؟ لماذا هذا ؟ هل هناك أي حالة حيث فارغة الصيد غير تصميم المقرر ؟

أعني, على سبيل المثال, في بعض الأحيان كنت ترغب في الحصول على بعض المعلومات الإضافية من مكان ما (خدمة ويب قاعدة بيانات) وكنت حقا لا أهتم إذا كنت سوف تحصل على هذه المعلومات أم لا.إذا كنت في محاولة للحصول على ذلك ، إذا حدث أي شيء, لا بأس, أنا مجرد إضافة "الصيد (استثناء تجاهل) {}" وهذا كل شيء

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

المحلول

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

وانها معادلة برمجة وضع شريط أسود على ضوء تحذير المحرك.

وأعتقد أن كيفية التعامل مع الاستثناءات يعتمد على ما طبقة من البرامج التي تعمل في: <لأ href = "http://nedbatchelder.com/text/exceptions-in-the-rainforest.html" يختلط = "noreferrer"> الاستثناءات في الغابات المطيرة .

نصائح أخرى

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

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

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

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

وعلى سبيل المثال، والنظر في بعض المكتبات المتشعب الخادم، وأنا لا يمكن أن الرعاية أقل إذا كان الخادم يلقي استثناء لأن العميل قد قطع وتعذر إرسال index.html.

وهناك حالات نادرة حيث يمكن تبريرها. في بايثون في كثير من الأحيان ترى هذا النوع من البناء:

try:
    result = foo()
except ValueError:
    result = None

وهكذا قد يكون موافق (حسب طلبك) القيام به:

result = bar()
if result == None:
    try:
        result = foo()
    except ValueError:
        pass # Python pass is equivalent to { } in curly-brace languages
 # Now result == None if bar() returned None *and* foo() failed

في مشروع صافي مؤخرا، كان لي لكتابة التعليمات البرمجية تعداد دلس البرنامج المساعد للعثور على الفئات التي تقوم بتنفيذ واجهة معينة. بت ذات الصلة من التعليمات البرمجية (في VB.NET، آسف) هي:

    For Each dllFile As String In dllFiles
        Try
            ' Try to load the DLL as a .NET Assembly
            Dim dll As Assembly = Assembly.LoadFile(dllFile)
            ' Loop through the classes in the DLL
            For Each cls As Type In dll.GetExportedTypes()
                ' Does this class implement the interface?
                If interfaceType.IsAssignableFrom(cls) Then

                    ' ... more code here ...

                End If
            Next
        Catch ex As Exception
            ' Unable to load the Assembly or enumerate types -- just ignore
        End Try
    Next

وعلى الرغم من أن حتى في هذه الحالة، ويهمني أن نعترف بأن تسجيل الفشل في مكان ما ربما يكون تحسنا.

وعادة ما يتم وضع

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

وعلى صعيد ذات صلة، فإن معظم الناس لا يعرفون أن كتلة حاول {} يمكن اتباعها مع أي صيد {} أو {} أخيرا، مطلوب واحد فقط.

يجب فقط أن يلقى

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

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

وأعتقد أنه بخير إذا قبض على خاص نوع استثناء من الذي أعلم أنه لن يؤدي الا الى أن تثار ل<م> خاص سبب واحد، وتتوقع أن استثناء وحقا لا تحتاج إلى القيام بأي شيء حيال ذلك.

ولكن حتى في هذه الحالة، قد يكون رسالة التصحيح في النظام.

في جوش بلوك - البند 65:لا تتجاهل استثناءات من فعالة جافا:

  1. فارغة catch الهزائم الغرض من الاستثناءات
  2. على الأقل كتلة catch يجب أن تحتوي على تعليق شرح السبب في أنه من المناسب أن تجاهل استثناء.

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

وانها مماثلة لOn Error Resume Next VB6، إلا أن كل شيء في كتلة المحاولة بعد طرح استثناء سيتم تخطي.

والذي لا يساعد عندما يكسر شيئا في ذلك الوقت.

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

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

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

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

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

وانها ربما لم الشيء الصحيح لأنك تمر بصمت <م> كل استثناء محتمل. إذا كان هناك استثناء معين كنت تتوقع، ثم يجب اختبار لذلك، rethrow إذا لم يكن استثناء الخاص بك.

try
{
    // Do some processing.
}
catch (FileNotFound fnf)
{
    HandleFileNotFound(fnf);
}
catch (Exception e)
{
    if (!IsGenericButExpected(e))
        throw;
}

public bool IsGenericButExpected(Exception exception)
{
    var expected = false;
    if (exception.Message == "some expected message")
    {
        // Handle gracefully ... ie. log or something.
        expected = true;
    }

    return expected;
}

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

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

ومثال آخر: CLR 2.0 غيرت الطريقة التي يتم التعامل مع الاستثناءات غير المعالجة على موضوع finalizer. قبل 2.0 سمح للعملية من أجل البقاء هذا السيناريو. في CLR الحالي هو إنهاء العملية في حالة استثناء غير معالج في موضوع finalizer.

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

<اقتباس فقرة> أعني، على سبيل المثال، في بعض الأحيان كنت ترغب في الحصول على بعض المعلومات الإضافية من مكان ما (خدمة ويب، قاعدة بيانات) وكنت حقا لا يهمني إذا كنت ستحصل على هذه المعلومات أم لا. لذلك يمكنك محاولة للحصول عليه، وإذا كان أي شيء يحدث، وهذا طيب، أنا مجرد إضافة "الصيد (استثناء تجاهل) {}" وهذا كل شيء

وهكذا، والذهاب مع المثال الخاص بك، انها فكرة سيئة في هذه الحالة لأنك صيد وتجاهل <م> جميع الاستثناءات. لو كنت اصطياد EInfoFromIrrelevantSourceNotAvailable فقط وتجاهل ذلك، من شأنه أن يكون على ما يرام، ولكن كنت لا. كنت تجاهل أيضا ENetworkIsDown، التي قد تكون أو لا تكون مهمة. كنت تجاهل ENetworkCardHasMelted وEFPUHasDecidedThatOnePlusOneIsSeventeen، والتي هي بالتأكيد تقريبا أهمية.

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

هناك حالات حيث قد تستخدم لهم ، ولكن ينبغي أن تكون نادرة جدا.الحالات التي لا يمكن استخدام واحد وتشمل:

  • استثناء قطع الأشجار ؛ اعتمادا على السياق قد ترغب في استثناء غير معالج أو رسالة نشرت بدلا من ذلك.

  • حلقات التقنية الحالات ، مثل تقديم أو معالجة الصوت أو مربع قائمة الاستدعاء ، حيث السلوك في حد ذاته سوف تظهر مشكلة رمي استثناء فقط سوف تحصل في الطريق و التسجيل استثناء من المحتمل ان يؤدي إلى 1000 من "فشل XXX" الرسائل.

  • البرامج التي لا تفشل ، على الرغم من أنها لا يزال ينبغي على الأقل أن تكون تسجيل شيئا.

معظم winforms التطبيقات, لقد وجدت أنه يكفي أن يكون لديك محاولة واحدة البيان لكل إدخال المستخدم.أنا استخدم الطرق التالية:(AlertBox هو مجرد سريعة MessageBox.عرض المجمع)

  public static bool TryAction(Action pAction)
  {
     try { pAction(); return true; }
     catch (Exception exception)
     {
        LogException(exception);
        return false;
     }
  }

  public static bool TryActionQuietly(Action pAction)
  {
     try { pAction(); return true; }
     catch(Exception exception)
     {
        LogExceptionQuietly(exception);
        return false;
     }
  }

  public static void LogException(Exception pException)
  {
     try
     {
        AlertBox(pException, true);
        LogExceptionQuietly(pException);
     }
     catch { }
  }

  public static void LogExceptionQuietly(Exception pException)
  {
     try { Debug.WriteLine("Exception: {0}", pException.Message); } catch { }
  }

ثم كل معالج الحدث يمكن أن تفعل شيئا مثل:

  private void mCloseToolStripMenuItem_Click(object pSender, EventArgs pEventArgs)
  {
     EditorDefines.TryAction(Dispose);
  }

أو

  private void MainForm_Paint(object pSender, PaintEventArgs pEventArgs)
  {
     EditorDefines.TryActionQuietly(() => Render(pEventArgs));
  }

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

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

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

        try
        {
            string a = "125";
            int b = int.Parse(a);
        }
        catch (Exception ex)
        {
            Log.LogError(ex);
        }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top