অ্যাক্সেসযোগ্য কোড, তবে একটি ব্যতিক্রম সহ অ্যাক্সেসযোগ্য


108

এই কোডটি এমন একটি অ্যাপ্লিকেশনের অংশ যা একটি ওডিবিসি সংযুক্ত ডাটাবেস থেকে পড়ে এবং লিখে। এটি ডাটাবেসে একটি রেকর্ড তৈরি করে এবং তারপরে পরীক্ষা করে রেকর্ডটি সফলভাবে তৈরি করা হয়েছে কিনা, তারপরে ফিরে আসবে true

নিয়ন্ত্রণ প্রবাহ সম্পর্কে আমার বোঝা নীচে রয়েছে:

command.ExecuteNonQuery()Invalid​Operation​Exception"বস্তুর বর্তমান অবস্থার জন্য কোনও মেথড কল অবৈধ" থাকাকালীন নথিভুক্ত করা হয় । অতএব, যদি এটি ঘটে থাকে, tryব্লকের কার্যকর হওয়া finallyবন্ধ হয়ে যাবে, ব্লকটি কার্যকর হবে, তারপরে return false;নীচের অংশে চালিত হবে ।

তবে, আমার আইডিই দাবি করে যে এটি return false;অ্যাক্সেসযোগ্য কোড। এবং এটি সত্য বলে মনে হচ্ছে, আমি এটিকে সরাতে পারি এবং এটি কোনও অভিযোগ ছাড়াই সংকলন করে। যাইহোক, আমার জন্য এটি দেখে মনে হচ্ছে যে উল্লিখিত ব্যতিক্রমটি ছুঁড়ে দেওয়া কোড পথের কোনও ফেরতের মান থাকবে না be

private static bool createRecord(String table,
                                 IDictionary<String,String> data,
                                 System.Data.IDbConnection conn,
                                 OdbcTransaction trans) {

    [... some other code ...]

    int returnValue = 0;
    try {
        command.CommandText = sb.ToString();
        returnValue = command.ExecuteNonQuery();

        return returnValue == 1;
    } finally {
        command.Dispose();
    }

    return false;
}

আমার বোঝার ভুল এখানে কী?



41
পার্শ্ব দ্রষ্টব্য: Disposeসুস্পষ্টভাবে কল করবেন না , তবে লিখুন using:using (var command = ...) {command.CommandText = sb.ToString(); return command.ExecuteNonQuery(); }
দিমিত্রি বাইচেনকো

7
একটি finallyব্লক মানে যা আপনি ভাবেন তার চেয়ে অন্য কিছু।
থরবজর্ন রাভন অ্যান্ডারসন

উত্তর:


149

সংকলক সতর্কতা (স্তর 2) CS0162

অ্যাক্সেসযোগ্য কোড সনাক্ত করা হয়েছে

সংকলক কোডটি সনাক্ত করেছে যা কখনই কার্যকর করা হবে না।

কোনটি ঠিক বলছে না, কম্পাইলার মাধ্যমে যথেষ্ট বুঝতে পারে স্ট্যাটিক বিশ্লেষণ এটি পৌঁছে যাবে নাকিসুরে কথা এবং সম্পূর্ণরূপে কম্পাইল থেকে এটা বাদ আইএল (অত: পর আপনার সাবধানবাণী)

দ্রষ্টব্য : আপনি ডিবাগারের সাথে অ্যাক্সেসযোগ্য কোডে পদক্ষেপ নেওয়ার চেষ্টা করে বা একটি আইএল এক্সপ্লোরার ব্যবহার করে নিজের পক্ষে এই সত্যটি প্রমাণ করতে পারেন

finallyএকটি অন পরতে পারেন ব্যতিক্রম , (যদিও সরাইয়া) এটা সত্য (এই ক্ষেত্রে) পরিবর্তন করে না এটি এখনও একটি হতে হবে Uncaught ব্যতিক্রম । কিন্তু, শেষ returnকখনই নির্বিশেষে আঘাত পাবেন না।

  • আপনি শেষ সম্মুখের অব্যাহত রাখার জন্য কোড চান return, আপনার একমাত্র বিকল্প হয় ক্যাচ ব্যতিক্রম ;

  • যদি আপনি না করেন তবে এটি ঠিক সেভাবেই ছেড়ে দিন এবং এটিকে সরিয়ে দিন return

উদাহরণ

try 
{
    command.CommandText = sb.ToString();
    returnValue = command.ExecuteNonQuery();

    return returnValue == 1;
}
catch(<some exception>)
{
   // do something
}
finally 
{
    command.Dispose();
}

return false;

ডকুমেন্টেশন উদ্ধৃতি

শেষ পর্যন্ত চেষ্টা করুন (সি # রেফারেন্স)

শেষ অবধি ব্যবহার করে, আপনি চেষ্টা ব্লকে বরাদ্দকৃত যে কোনও সংস্থান সাফ করতে পারেন এবং চেষ্টা ব্লকে কোনও ব্যতিক্রম ঘটে গেলেও আপনি কোড চালাতে পারেন। সাধারণত, নিয়ন্ত্রণ যখন একটি চেষ্টা করার স্টেটমেন্ট ছেড়ে দেয় তখন অবশেষে ব্লকের স্টেটমেন্টগুলি চলে। নিয়ন্ত্রণের স্থানান্তরটি সাধারণ সম্পাদন, বিরতি কার্যকরকরণ, চালিয়ে যাওয়া, গোটো বা রিটার্ন বিবৃতি বা ট্রায়াল স্টেটমেন্টের বাইরে কোনও ব্যতিক্রম প্রচারের ফলস্বরূপ ঘটতে পারে।

একটি পরিচালিত ব্যতিক্রমের মধ্যে, সম্পর্কিত অবশেষে ব্লকটি চালানোর গ্যারান্টিযুক্ত। যাইহোক, যদি ব্যতিক্রমটি নিয়ন্ত্রণহীন হয়, অবশেষে ব্লকটি কার্যকর করা ব্যতিক্রমটি কীভাবে অপসারণের অপারেশনটি ট্রিগার করা হয় তার উপর নির্ভর করে। এটি, আপনার কম্পিউটার কীভাবে সেট আপ হয় তার উপর নির্ভর করে।

সাধারণত, যখন কোনও অযথিত ব্যতিক্রম কোনও অ্যাপ্লিকেশন শেষ করে, অবশেষে ব্লকটি চালিত হয় কি না তা গুরুত্বপূর্ণ নয়। যাইহোক, যদি আপনার অবশেষে ব্লকের বিবৃতি থাকে যা অবশ্যই সেই পরিস্থিতিতে চালানো উচিত, একটি সমাধান হ'ল চেষ্টা অবশেষে বিবৃতিতে একটি ক্যাচ ব্লক যুক্ত করা । বিকল্পভাবে, আপনি কল স্ট্যাকের উচ্চতর আপ চেষ্টা-শেষ বিবৃতিতে চেষ্টা ব্লক নিক্ষেপ করা হতে পারে যে ব্যতিক্রম ধরতে পারেন । অর্থাত, আপনি যে পদ্ধতিটিতে কলটি ব্যবহার করে যা শেষ পর্যন্ত স্টেটমেন্ট স্টেটমেন্ট থাকে সেই পদ্ধতিতে বা সেই পদ্ধতিটিকে কল দেয় এমন পদ্ধতিতে বা কল স্ট্যাকের কোনও পদ্ধতিতে আপনি ব্যতিক্রমটি ধরতে পারেন। ব্যতিক্রম ধরা না পড়লে, অপারেটিং সিস্টেমটি একটি ব্যতিক্রম অদলিত ক্রিয়াকলাপটি ট্রিগার করতে পছন্দ করে কিনা তার উপর অবশেষে ব্লকটির সম্পাদন নির্ভর করে।

সর্বশেষে

IDisposableইন্টারফেস সমর্থন করে এমন কোনও কিছু ব্যবহার করার সময় (যা নিয়ন্ত্রণহীন সংস্থানগুলি ছাড়ার জন্য ডিজাইন করা হয়েছে), আপনি এটি একটি usingবিবৃতিতে মোড়ানো করতে পারেন । সংকলকটি বস্তুর উপর একটি try {} finally {}এবং অভ্যন্তরীণ কল উত্পন্ন করবেDispose()


1
প্রথম বাক্যে আইএল বলতে কী বোঝ?
ক্লকওয়ার্ক

2
@ ক্লক ওয়ার্ক আইএল উচ্চ স্তরের। নেট ভাষায় লিখিত কোড সংকলনের একটি পণ্য। একবার আপনি এই ভাষাগুলির একটিতে আপনার লিখিত কোডটি সংকলন করার পরে, আপনি আইএল থেকে তৈরি একটি বাইনারি পাবেন। দ্রষ্টব্য যে মধ্যবর্তী ভাষা কখনও কখনও কমন ইন্টারমিডিয়েট ল্যাঙ্গুয়েজ (সিআইএল) বা মাইক্রোসফ্ট ইন্টারমিডিয়েট ল্যাঙ্গুয়েজ (
এমএসআইএল

1
সংক্ষেপে, কারণ তিনি সম্ভাব্যতাগুলি ধরেন নি: হ'ল চেষ্টাটি রান অবধি ফিরে না আসা অবধি অবশেষে নীচে ফিরে আসাটিকে উপেক্ষা করবে বা একটি ব্যতিক্রম ছুঁড়েছে এবং সেই রিটার্ন কখনই পৌঁছাতে পারে না কারণ একটি ব্যতিক্রমের কারণে ফাংশনটি প্রস্থান করবে ither নিক্ষিপ্ত।
ফ্লিপ

86

শেষ অবধি কার্যকর করা হবে, তারপরে মিথ্যা রিটার্ন কার্যকর করা হবে; নিচে.

ভুল। finallyব্যতিক্রম গিলে না। এটি এটি সম্মান করে এবং ব্যতিক্রমটি স্বাভাবিক হিসাবে নিক্ষেপ করা হবে। এটি কেবল অবশেষে কোডটি কার্যকর করে ব্লকটি শেষ হওয়ার আগে (ব্যতিক্রম সহ বা ছাড়াই)।

আপনি যদি ব্যতিক্রমটি গ্রাস করতে চান তবে আপনার catchকোনও ব্লক ব্যবহার করা উচিত throw


1
উপরের সিনপেটটি ব্যতিক্রম ক্ষেত্রে সংকলন করবে, কী ফিরিয়ে দেওয়া হবে?
এহসান সাজ্জাদ

3
এটি সংকলন করে, তবে এটি কখনও আঘাত করবে না return falseকারণ এটি এর পরিবর্তে @ এহসান সাজ্জাদ
প্যাট্রিক হফম্যান

1
অদ্ভুত বলে মনে হচ্ছে, সংকলনগুলি কারণ এটি ব্যতিক্রম ব্যতির ক্ষেত্রে বুলের জন্য একটি মূল্য ফেরত দেবে এবং ব্যতিক্রমের ক্ষেত্রে কিছুই হবে না, সুতরাং পদ্ধতির ফেরতের ধরণটি সন্তুষ্ট করার জন্য বৈধ?
এহসান সাজ্জাদ

2
সংকলকটি কেবল রেখাকে উপেক্ষা করবে, সতর্কতার জন্য এটিই। তাহলে কেন সেই অদ্ভুত? @ এহসান সাজ্জাদ
প্যাট্রিক হফম্যান

3
মজার বিষয়: এটা আসলে না নিশ্চিত করে একটি পরিশেষে ব্লক যদি ব্যতিক্রম প্রোগ্রামে ধরা হয় না চালানো হবে। অনুমানটি এর গ্যারান্টি দেয় না এবং প্রারম্ভিক সিএলআরগুলি শেষ অবধি কার্যকর করে না । আমি মনে করি 4.0 এর সাথে শুরু (আগেও হতে পারে) যে আচরণটি পরিবর্তিত হয়েছে, তবে অন্যান্য রানটাইমগুলি এখনও অন্যরকম আচরণ করতে পারে। বরং অবাক করা আচরণের জন্য তোলে।
ভু

27

সতর্কতা হ'ল কারণ আপনি ব্যবহার করেন নি catchএবং আপনার পদ্ধতিটি মূলত এইভাবে লেখা হয়েছে:

bool SomeMethod()
{
    return true;
    return false; // CS0162 Unreachable code detected
}

যেহেতু আপনি finallyকেবল নিষ্পত্তি করতে ব্যবহার করেন , তাই পছন্দসই সমাধান হ'ল usingপ্যাটার্নটি ব্যবহার করুন :

using(var command = new WhateverCommand())
{
     ...
}

কী Disposeবলা হবে তা নিশ্চিত করার জন্য এটি যথেষ্ট । কোড ব্লকের সফল প্রয়োগের পরে বা কল স্ট্যাকের কিছুটা catch নীচে (আগে পিতামাতার কলগুলি ঠিক আছে, ডান?) এর কল করার নিশ্চয়তা রয়েছে ।

এটি নিষ্পত্তি সম্পর্কে না হয়, তাহলে

try { ...; return true; } // only one return
finally { ... }

যথেষ্ট, যেহেতু আপনাকে কখনইfalse পদ্ধতির শেষে ফিরে আসতে হবে না (সেই লাইনের প্রয়োজন নেই)। আপনার পদ্ধতিটি হ'ল কমান্ড এক্সিকিউশন ( trueবা false) এর রিটার্নের ফলাফল বা অন্যথায় ব্যতিক্রম ছুঁড়ে ফেলবে ।


প্রত্যাশিত ব্যতিক্রম মোড়ক দ্বারা নিজস্ব ব্যতিক্রম ছোঁড়ার জন্যও বিবেচনা করুন ( অবৈধ অপশন এক্সেক্সশন কনস্ট্রাক্টর দেখুন ):

try { ... }
catch(SomeExpectedException e)
{
    throw new SomeBetterExceptionWithExplanaition("...", e);
}

এটি সাধারণত নেস্টেড কল ব্যতিক্রম বলার অপেক্ষা রাখে কলারের কাছে আরও কিছু অর্থপূর্ণ (দরকারী) বলতে ব্যবহৃত হয়।


বেশিরভাগ সময় আপনি সত্যিই অযথিত ব্যতিক্রমগুলি সম্পর্কে চিন্তা করেন না। কখনও কখনও আপনাকে finallyব্যতিরেকে নিয়ন্ত্রণহীন অবস্থায় থাকলেও এটি নিশ্চিত করা দরকার । এক্ষেত্রে আপনি নিজেই এটি ধরেন এবং পুনরায় নিক্ষেপ করুন ( এই উত্তরটি দেখুন ):

try { ... }
catch { ...; throw; } // re-throw
finally { ... }

14

দেখে মনে হচ্ছে আপনি এরকম কিছু খুঁজছেন:

private static bool createRecord(string table,
                                 IDictionary<String,String> data,
                                 System.Data.IDbConnection conn,
                                 OdbcTransaction trans) {
  [... some other code ...]

  // Using: do not call Dispose() explicitly, but wrap IDisposable into using
  using (var command = ...) {
    try {
      // Normal flow:
      command.CommandText = sb.ToString();

      // True if and only if exactly one record affected
      return command.ExecuteNonQuery() == 1;
    }
    catch (DbException) {
      // Exceptional flow (all database exceptions)
      return false;
    }
  }
}

দয়া করে নোট করুন, এটি কোনও ব্যতিক্রম finally গ্রাস করে না

finally {
  // This code will be executed; the exception will be efficently re-thrown
}

// And this code will never be reached

8

আপনার কোনও catchব্লক নেই, তাই ব্যতিক্রমটি এখনও ছুঁড়ে দেওয়া হয়েছে, যা প্রত্যাবর্তনকে অবরুদ্ধ করে।

শেষ অবধি কার্যকর করা হবে, তারপরে মিথ্যা রিটার্ন কার্যকর করা হবে; নিচে.

এটি ভুল, কারণ অবশেষে ব্লকটি কার্যকর করা হবে এবং তারপরে একটি অপ্রকাশিত ব্যতিক্রম থাকবে।

finallyব্লকগুলি ক্লিনআপের জন্য ব্যবহৃত হয় এবং সেগুলি ব্যতিক্রম হয় না। ব্যতিক্রম প্রত্যাবর্তনের আগে নিক্ষেপ করা হয়, অতএব, রিটার্ন কখনই পৌঁছাতে পারে না, কারণ একটি ব্যতিক্রম আগে ফেলে দেওয়া হয়।

আপনার আইডিই সঠিক যে এটি কখনই পৌঁছাবে না, কারণ ব্যতিক্রম ছুঁড়ে দেওয়া হবে। কেবলমাত্র catchব্লকগুলি ব্যতিক্রমগুলি ধরতে সক্ষম।

ডকুমেন্টেশন থেকে পড়া ,

সাধারণত, যখন কোনও অযথিত ব্যতিক্রম কোনও অ্যাপ্লিকেশন শেষ করে, অবশেষে ব্লকটি চালিত হয় কি না তা গুরুত্বপূর্ণ নয়। যাইহোক, যদি আপনার অবশেষে ব্লকের বিবৃতি থাকে যা অবশ্যই সেই পরিস্থিতিতে চালানো উচিত, একটি সমাধান হ'ল চেষ্টা অবশেষে বিবৃতিতে একটি ক্যাচ ব্লক যুক্ত করা । বিকল্পভাবে, আপনি কল স্ট্যাকের উচ্চতর আপ চেষ্টা-শেষ বিবৃতিতে চেষ্টা ব্লক নিক্ষেপ করা হতে পারে যে ব্যতিক্রম ধরতে পারেন। অর্থাত, আপনি যে পদ্ধতিটিতে কলটি ব্যবহার করে যা শেষ পর্যন্ত স্টেটমেন্ট স্টেটমেন্ট থাকে সেই পদ্ধতিতে বা সেই পদ্ধতিটিকে কল দেয় এমন পদ্ধতিতে বা কল স্ট্যাকের কোনও পদ্ধতিতে আপনি ব্যতিক্রমটি ধরতে পারেন। ব্যতিক্রম ধরা না পড়লে, অপারেটিং সিস্টেমটি একটি ব্যতিক্রম অদলিত ক্রিয়াকলাপটি ট্রিগার করতে পছন্দ করে কিনা তার উপর অবশেষে ব্লকটির সম্পাদন নির্ভর করে

এটি স্পষ্টভাবে দেখায় যে অবশেষে ব্যতিক্রমটি ধরার উদ্দেশ্যে নয় এবং catchবিবৃতি দেওয়ার আগে কোনও খালি বক্তব্য থাকলে আপনি সঠিক হয়ে finallyউঠতেন।


7

যখন ব্যতিক্রম নিক্ষেপ করা হয়, স্ট্যাকটি কোনও মান না ফেরৎ আনইন্ডাইন্ড (এক্সিকিউশনটি ফাংশন থেকে সরে যাবে) হয়ে যাবে এবং ফাংশনের উপরে স্ট্যাক ফ্রেমের কোনও ক্যাচ ব্লক পরিবর্তে ব্যতিক্রমটিকে ধরে ফেলবে।

অতএব, return falseকার্যকর করা হবে না।

নিয়ন্ত্রণ প্রবাহটি বোঝার জন্য ম্যানুয়ালি একটি ব্যতিক্রম ছোঁড়ার চেষ্টা করুন:

try {
    command.CommandText = sb.ToString();
    returnValue = command.ExecuteNonQuery();

    // Try this.
    throw new Exception("See where this goes.");

    return returnValue == 1;
} finally {
    command.Dispose();
}

5

আপনার কোডে:

private static bool createRecord(String table, IDictionary<String,String> data, System.Data.IDbConnection conn, OdbcTransaction trans) {

    [... some other code ...]

    int returnValue = 0;
    try {
        command.CommandText = sb.ToString();
        returnValue = command.ExecuteNonQuery();

        return returnValue == 1; // You return here in case no exception is thrown
    } finally {
        command.Dispose(); //You don't have a catch so the exception is passed on if thrown
    }

    return false; // This is never executed because there was either one of the above two exit points of the method reached.
}

শেষ অবধি কার্যকর করা হবে, তারপরে মিথ্যা রিটার্ন কার্যকর করা হবে; নিচে

এটি আপনার যুক্তিযুক্ত ত্রুটি কারণ finallyব্লকটি ব্যতিক্রমটি ধরবে না এবং এটি কখনই শেষ ফেরতের বিবৃতিতে পৌঁছাবে না।


4

সর্বশেষ বিবৃতিটি return falseঅ্যাক্সেসযোগ্য নয়, কারণ চেষ্টা ব্লকটি এমন একটি catchঅংশ হারিয়েছে যা ব্যতিক্রমটি পরিচালনা করতে পারে, সুতরাং finallyব্লকের পরে ব্যতিক্রমটি পুনর্বিবেচনা করা হয় এবং এক্সিকিউশন কখনই শেষ বিবৃতিতে পৌঁছায় না।


2

আপনার কোডে আপনার দুটি রিটার্ন পাথ রয়েছে যার মধ্যে দ্বিতীয়টি প্রথমটির কারণে অ্যাক্সেসযোগ্য। আপনার tryব্লকের সর্বশেষ বিবৃতিটি return returnValue == 1;আপনার স্বাভাবিক রিটার্ন সরবরাহ করে, যাতে আপনি কখনই return false;পদ্ধতি ব্লকের শেষে পৌঁছাতে পারবেন না ।

এফডাব্লুআইডাব্লু, finallyব্লকের সাথে সম্পর্কিত এক্সটেকশনের ক্রম: ট্রাই ব্লকে রিটার্ন মান সরবরাহকারী এক্সপ্রেশনটি প্রথমে মূল্যায়ন করা হবে, তারপরে অবশেষে ব্লকটি কার্যকর করা হবে এবং তারপরে গণনা করা এক্সপ্রেশন মানটি ফিরে আসবে (ট্রাই ব্লকের ভিতরে)।

ব্যতিক্রম প্রবাহ সম্পর্কে ... একটি ছাড়া catch, finallyব্যতিক্রমটি পদ্ধতিটি থেকে পুনর্বিবেচনার আগে ব্যতিক্রমের পরে উইল কার্যকর করা হবে; কোনও "ফেরত" পাথ নেই।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.