কেস ব্লকে কেন সি # এর স্থানীয় সুযোগ নেই?


38

আমি এই কোডটি লিখছিলাম:

private static Expression<Func<Binding, bool>> ToExpression(BindingCriterion criterion)
{
    switch (criterion.ChangeAction)
    {
        case BindingType.Inherited:
            var action = (byte)ChangeAction.Inherit;
            return (x => x.Action == action);
        case BindingType.ExplicitValue:
            var action = (byte)ChangeAction.SetValue;
            return (x => x.Action == action);
        default:
            // TODO: Localize errors
            throw new InvalidOperationException("Invalid criterion.");
    }
}

এবং একটি সংকলন ত্রুটি পেয়ে অবাক হয়েছিল:

'কর্ম' নামে একটি স্থানীয় ভেরিয়েবল ইতিমধ্যে এই সুযোগে সংজ্ঞায়িত হয়েছে

এটি সমাধান করা খুব সহজ সমস্যা ছিল; দ্বিতীয়টি থেকে মুক্তি পেয়ে varকৌশলটি করেছিলেন।

স্পষ্টতই caseব্লকগুলিতে ঘোষিত ভেরিয়েবলগুলির পিতামাতার সুযোগ রয়েছে switchতবে আমি কেন আগ্রহী তা জানতে আগ্রহী। প্রদত্ত যে C # এর মৃত্যুদন্ড অন্যান্য ক্ষেত্রে মাধ্যমে পড়া (এটা অনুমতি দেয় না প্রয়োজন break , return, throw, অথবা goto caseযে শেষে বিবৃতি caseব্লক), এটা বেশ অদ্ভুত বলে মনে হয় এটি পরিবর্তনশীল ঘোষণা সম্ভব হবে ভিতরে এক caseঅন্য কোন ভেরিয়েবল সঙ্গে ব্যবহৃত বা দ্বন্দ্ব করা case। অন্য কথায় ভেরিয়েবলগুলি caseস্টেটমেন্টের মাধ্যমে পতনের জন্য প্রদর্শিত হয় যদিও কার্যকর হতে পারে না cannot বিভ্রান্ত বা সহজে বা অপব্যবহার করা অন্য ভাষার কিছু নির্মাণ নিষিদ্ধ করে পাঠযোগ্যতার প্রচার করতে সি # প্রচুর ব্যথা নেয় takes এটি দেখে মনে হচ্ছে এটি বিভ্রান্তির কারণ মাত্র। নিম্নলিখিত পরিস্থিতিতে বিবেচনা করুন:

  1. যদি এটিতে এটি পরিবর্তন করা হয়:

    case BindingType.Inherited:
        var action = (byte)ChangeAction.Inherit;
        return (x => x.Action == action);
    case BindingType.ExplicitValue:
        return (x => x.Action == action);
    

    আমি " আনসাইন করা স্থানীয় ভেরিয়েবলের ব্যবহার 'ক্রিয়া " পেয়েছি । এটি বিভ্রান্তিকর কারণ সি # তে থাকা প্রতিটি অন্যান্য নির্মাণে আমি var action = ...ভেরিয়েবলটি আরম্ভ করার কথা ভাবতে পারি , তবে এখানে এটি কেবল এটি ঘোষণা করে।

  2. আমি যদি কেসগুলিকে এভাবে পরিবর্তন করতে পারি:

    case BindingType.ExplicitValue:
        action = (byte)ChangeAction.SetValue;
        return (x => x.Action == action);
    case BindingType.Inherited:
        var action = (byte)ChangeAction.Inherit;
        return (x => x.Action == action);
    

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

  3. যদি এটিতে এটি পরিবর্তন করা হয়:

    case BindingType.Inherited:
        var action = (byte)ChangeAction.Inherit;
        return (x => x.Action == action);
    case BindingType.ExplicitValue:
        action = (byte)ChangeAction.SetValue;
        goto case BindingType.Inherited;
    

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

সুতরাং আমার প্রশ্নটি হল, কেন সি # এর ডিজাইনাররা caseব্লকগুলিকে তাদের নিজস্ব স্থানীয় সুযোগ দেয়নি ? এর কোনও historicalতিহাসিক বা প্রযুক্তিগত কারণ রয়েছে কি?


4
বিবৃতি actionদেওয়ার আগে আপনার পরিবর্তনশীল ঘোষণা করুন switch, বা প্রতিটি কেসকে তার নিজস্ব ব্রেসেসে রাখুন, এবং আপনি বুদ্ধিমান আচরণ পাবেন।
রবার্ট হার্ভে

3
@ রবার্টহার্ভে হ্যাঁ, এবং আমি আরও এগিয়ে যেতে এবং এটিকে মোটেও ব্যবহার না করেই লিখতে switchপারি - আমি এই নকশার পিছনে যুক্তি সম্পর্কে কেবল আগ্রহী।
PSWg

যদি সি # এর প্রতিটি মামলার পরে বিরতি প্রয়োজন তবে আমার ধারণা এটি সি / জাভা হিসাবে historicalতিহাসিক কারণে হতে পারে যা ঘটনাটি নয়!
tgkprog

@tgkprog আমি বিশ্বাস করি যে এটি historicalতিহাসিক কারণে নয় এবং সি # এর ডিজাইনাররা উদ্দেশ্য করে এটি নিশ্চিত করেছিলেন যে একটি ভুলে যাওয়ার সাধারণ ভুলটি breakসি # তে সম্ভব নয়।
সোভিক

12
সম্পর্কিত এসও প্রশ্নের উপর এরিক লিপার্টের উত্তর দেখুন। stackoverflow.com/a/1076642/414076 আপনি সন্তুষ্ট হতে পারেন বা নাও আসতে পারেন। এটি হিসাবে লেখা হয়েছে "কারণ তারা 1999 এ এটি করতে বেছে নিয়েছিল" "
অ্যান্টনি পেগ্রাম

উত্তর:


24

আমি মনে করি একটি ভাল কারণ হ'ল প্রতিটি ক্ষেত্রে, একটি "সাধারণ" স্থানীয় পরিবর্তনশীলের ক্ষেত্রটি ব্রেস ( ) দ্বারা সীমাবদ্ধ একটি ব্লক{}forলুপ ভেরিয়েবল বা ঘোষিত একটি ভেরিয়েবলের মতো স্থানীয় বিবরণগুলি যা সাধারণ নয় সেগুলি স্টেটমেন্টের আগে (যা সাধারণত একটি ব্লক) একটি বিশেষ নির্মাণে উপস্থিত হয় using

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

রেফারেন্সের জন্য, নিয়মগুলি সি # স্পেসের .73.7 স্কোপে রয়েছে:

  • স্থানীয় ভেরিয়েবল-ঘোষণায় ঘোষিত একটি স্থানীয় ভেরিয়েবলের সুযোগ হ'ল সেই ব্লকটি যেখানে ঘোষণাপত্রটি ঘটে।

  • একটি বিবৃতিটির স্যুইচ-ব্লকে একটি স্থানীয় ভেরিয়েবলের ঘোষিত সুযোগটি switchহ'ল স্যুইচ-ব্লক

  • একটি স্থানীয় পরিবর্তনশীল এর সুযোগ ঘোষিত একটি জন্য-সূচনাকারী একটি এর forবিবৃতি জন্য-সূচনাকারী , জন্য-শর্ত , জন্য-পুনরুক্তিকারীর , এবং অন্তর্ভুক্ত বিবৃতি এর forবিবৃতি।

  • একটি পরিবর্তনশীল এর সুযোগ ঘোষিত একটি অংশ হিসেবে foreach-বিবৃতি , ব্যবহার-বিবৃতি , লক-বিবৃতি বা কোয়েরি প্রকাশ দেওয়া কনস্ট্রাক্ট সম্প্রসারণ দ্বারা নির্ধারিত হয়।

(যদিও আমি পুরোপুরি নিশ্চিত নই যে কেন switchব্লকটি স্পষ্টভাবে উল্লেখ করা হয়েছে, যেহেতু এটিতে অন্যান্য উল্লিখিত সমস্ত নির্মাণের মত স্থানীয় ভেরিয়েবল ঘোষণার জন্য কোনও বিশেষ সিনট্যাক্স নেই।)


1
+1 আপনি যে সুযোগটি উদ্ধৃত করছেন তার লিঙ্ক সরবরাহ করতে পারবেন?
PSwg

@pswg আপনি এমএসডিএন-তে স্পেসিফিকেশন ডাউনলোডের জন্য একটি লিঙ্ক খুঁজে পেতে পারেন । (সেই পৃষ্ঠায় "মাইক্রোসফ্ট ডেভেলপার নেটওয়ার্ক (এমএসডিএন)" লিঙ্কটি ক্লিক করুন))
এভিচ

তাই আমি জাভা চশমাগুলি সন্ধান করেছি এবং switchesএই বিষয়ে একযোগে আচরণ করব বলে মনে হচ্ছে (এর শেষে লাফ দেওয়ার দরকার বাদে case)। মনে হয় এই আচরণটি সেখান থেকে অনুলিপি করা হয়েছিল। সুতরাং আমি অনুমান করি যে সংক্ষিপ্ত উত্তরটি হল - caseবিবৃতিগুলি ব্লক তৈরি করে না, তারা কেবল একটি switchব্লকের বিভাজনগুলি সংজ্ঞায়িত করে - এবং সেহেতু তারা নিজেরাই স্কোপগুলি রাখে না।
PSWg

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

42

তবে তা করে। এর সাথে লাইন মোড়ানো দ্বারা আপনি যে কোনও জায়গায় স্থানীয় স্কোপগুলি তৈরি করতে পারেন{}

switch (criterion.ChangeAction)
{
  case BindingType.Inherited:
    {
      var action = (byte)ChangeAction.Inherit;
      return (x => x.Action == action);
    }
  case BindingType.ExplicitValue:
    {
      var action = (byte)ChangeAction.SetValue;
      return (x => x.Action == action);
    }
  default:
    // TODO: Localize errors
    throw new InvalidOperationException("Invalid criterion.");
}

হ্যাঁ এটি ব্যবহার করেছে এবং এটি বর্ণিত হিসাবে কাজ করে
এমভিশন

1
+1 এটি একটি ভাল কৌশল, তবে আমি আমার আসল প্রশ্নটির নিকটতম আসার জন্য সাইক এর উত্তর গ্রহণ করতে চলেছি
pswg

10

আমি এরিক লিপার্টকে উদ্ধৃত করব, যার উত্তরটি বিষয়টি সম্পর্কে খুব স্পষ্ট:

একটি যুক্তিসঙ্গত প্রশ্ন "এটি আইনী কেন নয়?" একটি যুক্তিসঙ্গত উত্তর "ভাল, এটি কেন হওয়া উচিত"? আপনি এটি দুটি উপায়ের একটি হতে পারেন। হয় এটি আইনী:

switch(y) 
{ 
    case 1:  int x = 123; ...  break; 
    case 2:  int x = 456; ...  break; 
}

বা এটি আইনী:

switch(y) 
{
    case 1:  int x = 123; ... break; 
    case 2:  x = 456; ... break; 
}

কিন্তু আপনি এটি উভয় উপায়ে থাকতে পারে না। সি # এর ডিজাইনাররা এটি করার জন্য আরও প্রাকৃতিক উপায় বলে মনে করে দ্বিতীয় উপায় বেছে নিয়েছে।

এই সিদ্ধান্তটি দশ বছর আগে লাজুক, July ই জুলাই, ১৯৯ on সালে হয়েছিল। সেদিনের নোটগুলিতে দেওয়া মন্তব্যগুলি অত্যন্ত সংক্ষিপ্ত, কেবল "একটি সুইচ-কেস নিজস্ব ঘোষণার জায়গা তৈরি করে না" উল্লেখ করে এবং পরে কিছু নমুনা কোড দেয় যা কী কাজ করে এবং কী না তা দেখায়।

এই বিশেষ দিনে ডিজাইনারদের মনে কী ছিল সে সম্পর্কে আরও জানতে, আমি দশ বছর আগে তাদের চিন্তাভাবনাগুলি নিয়ে প্রচুর লোককে বাগ করতে হয়েছিল - এবং শেষ পর্যন্ত একটি তুচ্ছ বিষয় সম্পর্কে তাদের ত্রুটিযুক্ত করতে হবে; আমি এটা করতে যাচ্ছি না।

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

সুতরাং, আপনি যদি এরিক লিপার্টের চেয়ে 1999 এর সি # বিকাশকারী দলের সাথে আরও অন্তরঙ্গ না হন তবে আপনি সঠিক কারণটি কখনই জানতে পারবেন না!


কোনও ডাউনভোটার নয়, গতকাল এই প্রশ্নের উপর মন্তব্য করা হয়েছিল ।
জেসি সি। স্লাইসার

4
আমি এটি দেখতে পাচ্ছি, তবে যেহেতু মন্তব্যকারী কোনও উত্তর পোস্ট করেনি, তাই আমি ভেবেছিলাম লিঙ্কের বিষয়বস্তু উদ্ধৃত করে স্পষ্টরূপে আনসার তৈরি করা ভাল ধারণা হতে পারে। আমি ডাউনভোটদের যত্ন নিই না! ওপি "তিহাসিক কারণ জিজ্ঞাসা করে, "এটি কীভাবে করবেন" উত্তর নয়।
সিরিল গ্যান্ডন

5

ব্যাখ্যাটি সহজ - কারণ এটি সি এর মতো সি ++, জাভা এবং সি # এর মতো ভাষা পরিচিতির জন্য স্যুইচ বিবৃতিটির বাক্য গঠন এবং স্কোপিং অনুলিপি করেছে।

(অন্য উত্তরে যেমন বলা হয়েছে, সি # এর বিকাশকারীদের কীভাবে কেস-স্কোপ সম্পর্কিত এই সিদ্ধান্ত নেওয়া হয়েছিল সে সম্পর্কে দলিল নেই have তবে সি # সিনট্যাক্সের জন্য অ-নিয়ন্ত্রিত নীতিটি ছিল যে তারা যদি এটির ভিন্নভাবে করার বাধ্যতামূলক কারণ না দেয় তবে তারা জাভা অনুলিপি করেছিলেন। )

সি-তে, কেস স্টেটমেন্টগুলি গোটো-লেবেলের মতো। স্যুইচ স্টেটমেন্টটি একটি গণিত গোটোয়ের জন্য সত্যই একটি সুন্দর সিনট্যাক্স । কেসগুলি সুইচ ব্লকে প্রবেশের পয়েন্টগুলি সংজ্ঞায়িত করে । ডিফল্টরূপে বাকী কোডটি কার্যকর করা হবে, যদি না স্পষ্টভাবে প্রস্থান হয়। সুতরাং এটি কেবল একই বোঝায় যে তারা একই সুযোগ ব্যবহার করে।

(আরও মৌলিকভাবে। গোটো কাঠামোগত নয় - তারা কোডের বিভাগগুলি সংজ্ঞায়িত বা সীমিত করে না , তারা কেবল জাম্প-পয়েন্টগুলিই সংজ্ঞায়িত করে Therefore সুতরাং গোটো লেবেল কোনও সুযোগ প্রবর্তন করতে পারে না ))

সি # বাক্য গঠন ধরে রাখে, তবে প্রতিটি (খালি নয়) কেস ক্লজের পরে একটি প্রস্থান প্রয়োজন হয়ে "পড়ুন" এর বিরুদ্ধে একটি সুরক্ষার পরিচয় দেয়। তবে এই পরিবর্তনটি আমরা কীভাবে স্যুইচটির কথা ভাবি! কেসগুলি এখন বিকল্প শাখাগুলির মতো, যদি অন্য কোনও শাখার মতো। এর অর্থ আমরা প্রতিটি শাখা যদি তার নিজস্ব ক্ষেত্রকে ঠিক-ই-ক্লজ বা পুনরাবৃত্তির ধারাগুলির মতো সংজ্ঞায়িত করে আশা করব।

সুতরাং সংক্ষেপে: কেস একই স্কোপটি ভাগ করে দেয় কারণ এটি সি তে কেমন হয় তবে এটি সি # তে অদ্ভুত এবং অসঙ্গত বলে মনে হয় কারণ আমরা কেসগুলিকে লক্ষ্য লক্ষ্য না করে বিকল্প শাখা হিসাবে বিবেচনা করি।


1
" এটি সি # তে অদ্ভুত এবং অসঙ্গত বলে মনে হচ্ছে কারণ আমরা কেসগুলি লক্ষ্য লক্ষ্য না করে বিকল্প শাখা হিসাবে বিবেচনা করি " এটাই আমার ছিল ঠিক বিভ্রান্তির। সি # তে কেন এটি ভুল মনে হচ্ছে এর পিছনে নান্দনিক কারণ ব্যাখ্যা করার জন্য +1 ।
PSWg

4

সুযোগ দেখার এক সরল উপায় হ'ল ব্লকগুলি দ্বারা সুযোগ বিবেচনা করা {}

যেহেতু switchকোনও ব্লক নেই, তাই এটিতে বিভিন্ন স্কোপ থাকতে পারে না।


3
কি হবে for (int i = 0; i < n; i++) Write(i); /* legal */ Write(i); /* illegal */? কোনও ব্লক নেই, তবে বিভিন্ন স্কোপ রয়েছে।
সোভিক

@ এসভিক: যেমনটি আমি বলেছি, সরলীকৃত হয়েছে, সেখানে একটি ব্লক রয়েছে, যা forবিবৃতি দ্বারা তৈরি হয়েছিল । switchপ্রতিটি স্তরের ক্ষেত্রে কেবল শীর্ষ স্তরে ব্লক তৈরি করে না। সাদৃশ্যটি হ'ল প্রতিটি বিবৃতি একটি ব্লক তৈরি করে ( switchবিবৃতি হিসাবে গণনা করা)।
গুভান্তে

1
তারপরে আপনি কেন গণনা করতে পারবেন না case?
এসভিচ

1
@ এসভিক: কারণ আপনি caseকোনও বিকল্প যুক্ত করার সিদ্ধান্ত না নিলে কোনও ব্লক নেই। forপরবর্তী বিবরণের জন্য স্থায়ী হয় যতক্ষণ না আপনি যোগ করুন {}তাই এটির সর্বদা একটি ব্লক caseথাকে , তবে কোনও কিছু আপনাকে আসল ব্লক, switchবিবৃতি ছেড়ে না দেওয়ার আগ পর্যন্ত স্থায়ী হয় ।
গুভান্তে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.