سؤال

هل الاستخدام يمسك بالاستثناء أم يرميه؟أي.

using (StreamReader rdr = File.OpenText("file.txt"))
{
 //do stuff
}

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

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

المحلول

باستخدام البيانات لا تأكل الاستثناءات.

كل ما يفعله "الاستخدام" هو توسيع نطاق الكائن الخاص بك إلى كتلة الاستخدام، واستدعاء Dispose() تلقائيًا على الكائن عندما يغادر الكتلة.

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

نصائح أخرى

عندما ترى عبارة استخدام، فكر في هذا الكود:

StreadReader rdr = null;
try
{
    rdr = File.OpenText("file.txt");
    //do stuff
}
finally
{
    if (rdr != null)
        rdr.Dispose();
}

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

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

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

try
{
    using (
        StreamReader rdr = File.OpenText("file.txt"))
    { //do stuff 
    }
}
catch (FileNotFoundException Ex)
{
    // The file didn't exist
}
catch (AccessViolationException Ex)
{
    // You don't have the permission to open this
}
catch (Exception Ex)
{
    // Something happened! 
}

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

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

في المثال الخاص بك، إذا File.OpenText يلقي، Dispose سوف لا يدعى يسمى.

إذا حدث الاستثناء في //do stuff, ، ال Dispose سوف يدعى يسمى.

في كلتا الحالتين، عادةً ما يتم نشر الاستثناء خارج النطاق، كما سيكون بدون استخدام إفادة.

إذا لم تكتشف استثناءً على وجه التحديد، فسيتم طرحه في المكدس حتى يحدث شيء ما

لا يتعارض الاستخدام مع معالجة الاستثناءات بصرف النظر عن تنظيف الأشياء في نطاقه.

لا يتعامل مع الاستثناءات ولكنه يسمح للاستثناءات بالمرور.

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

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

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

"الاستخدام" لا يلتقط الاستثناءات، بل يتخلص فقط من الموارد في حالة وجود استثناءات لم تتم معالجتها.

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

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