সি # সুইচ স্টেটমেন্ট সীমাবদ্ধতা - কেন?


140

একটি স্যুইচ বিবৃতি লেখার সময়, ক্ষেত্রে বিবৃতিতে আপনি কী স্যুইচ করতে পারবেন তার দুটি সীমাবদ্ধতা উপস্থিত রয়েছে।

উদাহরণস্বরূপ (এবং হ্যাঁ, আমি জানি, আপনি যদি এই ধরণের কাজ করে থাকেন তবে এর অর্থ সম্ভবত আপনার অবজেক্ট-ওরিয়েন্টেড (ওও) আর্কিটেকচারটি যদি নিখুঁত হয় - এটি কেবল একটি স্বীকৃত উদাহরণ!),

  Type t = typeof(int);

  switch (t) {

    case typeof(int):
      Console.WriteLine("int!");
      break;

    case typeof(string):
      Console.WriteLine("string!");
      break;

    default:
      Console.WriteLine("unknown!");
      break;
  }

এখানে স্যুইচ () বিবৃতিটি 'প্রত্যাশিত অবিচ্ছেদ্য ধরণের মান' দিয়ে ব্যর্থ হয় এবং কেস স্টেটমেন্টগুলি 'একটি ধ্রুবক মান প্রত্যাশিত হয়' দিয়ে ব্যর্থ হয়।

কেন এই বিধিনিষেধগুলি স্থানে রয়েছে এবং এর অন্তর্নিহিত ন্যায়সঙ্গততা কী? কেন সুইচ বিবৃতি আমি কোন কারণে দেখতে না হয়েছে শুধুমাত্র স্ট্যাটিক বিশ্লেষণ কবলে কাছে, কেন মান হচ্ছে সুইচড অবিচ্ছেদ্য হতে (যে, আদিম) আছে। যৌক্তিকতা কী?



বিল্ট-ইন টাইপগুলিতে স্যুইচ করার জন্য আরেকটি বিকল্প হ'ল টাইপকোড এনাম
এরিক ফিলিপস

উত্তর:


98

এটি আমার আসল পোস্ট, যা কিছুটা বিতর্ক সৃষ্টি করেছিল ... কারণ এটি ভুল :

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


আসলে, সি # স্যুইচ স্টেটমেন্টটি সবসময় ধ্রুবক সময় শাখা হয় না

কিছু ক্ষেত্রে সংকলক একটি সিআইএল স্যুইচ স্টেটমেন্ট ব্যবহার করবে যা একটি লাফ টেবিল ব্যবহার করে প্রকৃতপক্ষে একটি ধ্রুবক সময় শাখা। যাইহোক, ইভান হ্যামিল্টনের নির্দেশিত হিসাবে খুব কম ক্ষেত্রে সংকলক পুরোপুরি অন্য কিছু তৈরি করতে পারে।

এটি বিভিন্ন সি # স্যুইচ স্টেটমেন্ট, কিছু স্পারস, কিছু ঘন, এবং ইলদাস.এক্স.এই.এস. সরঞ্জাম দ্বারা ফলাফল প্রাপ্ত সিআইএল দ্বারা যাচাই করে নেওয়া বেশ সহজ।


4
অন্যান্য উত্তরে (খনি সহ) উল্লিখিত হিসাবে, এই উত্তরে দাবিগুলি সঠিক নয়। আমি মুছে ফেলার সুপারিশ করব (যদি কেবল এটির (সম্ভবত প্রচলিত) ভুল ধারণাটি এড়াতে হয়)।
mweerden

দয়া করে নীচে আমার পোস্টটি দেখুন যেখানে আমি দেখি, আমার মতে চূড়ান্তভাবে, যে স্যুইচ বিবৃতিটি একটি ধ্রুবক সময় শাখা করে।
ব্রায়ান এনসিংক

আপনার উত্তর, ব্রায়ান আপনাকে অনেক ধন্যবাদ। অনুগ্রহ করে ইভান হ্যামিল্টনের জবাব ((48259) [ বিটা.স্ট্যাকওভারফ্লো / প্রশ্ন / 44905/#48259] ) দেখুন। সংক্ষেপে: আপনি সেই switch নির্দেশের বিষয়ে কথা বলছেন (সিআইএল-এর) যা switchসি # এর বক্তব্যের মতো নয় ।
mweerden

আমি বিশ্বাস করি না যে কোনওটি স্ট্রিংগুলিতে স্যুইচ করার সময় সংকলক স্থির-সময় শাখা তৈরি করে।
ড্র নোকস

এটি কি সি # 7.0 এ স্যুইচ কেস স্টেটমেন্টগুলিতে প্যাটার্ন মিলের সাথে প্রযোজ্য?
বি ড্যারেন ওলসন

114

সিআইএল স্যুইচ নির্দেশের সাথে সি # স্যুইচ বিবৃতিটি বিভ্রান্ত না করা গুরুত্বপূর্ণ।

সিআইএল স্যুইচটি একটি জাম্প টেবিল, যার জন্য জাম্প অ্যাড্রেসগুলির একটি সেটে একটি সূচক প্রয়োজন।

এটি কেবল তখনই কার্যকর যখন সি # সুইচের কেসগুলি সংলগ্ন হয়:

case 3: blah; break;
case 4: blah; break;
case 5: blah; break;

তবে এগুলি যদি না হয় তবে অল্প ব্যবহার:

case 10: blah; break;
case 200: blah; break;
case 3000: blah; break;

(আপনার কেবলমাত্র 3 টি স্লট ব্যবহৃত আকারের একটি টেবিলের 3000 প্রবেশের দরকার হবে)

অ-সংলগ্ন অভিব্যক্তিগুলির সাথে, সংকলক লিনিয়ার সম্পাদনা শুরু করতে পারে যদি-অন্যথায়-যদি-অন্যথায় পরীক্ষা করে।

বৃহত্তর অ-সংলগ্ন এক্সপ্রেশন সেটগুলির সাথে, সংকলকটি বাইনারি ট্রি অনুসন্ধানের সাথে শুরু করতে পারে এবং শেষ পর্যন্ত যদি অন্যথায় হয় তবে অন্য কয়েকটি শেষ আইটেম।

সংলগ্ন আইটেমগুলির ক্লাম্প সমন্বিত এক্সপ্রেশন সেটগুলির সাথে, সংকলকটি বাইনারি গাছের অনুসন্ধান এবং শেষ পর্যন্ত একটি সিআইএল স্যুইচ করতে পারে।

এটি "মাইস" এবং "মাইটস" পূর্ণ, এবং এটি সংকলকটির উপর নির্ভরশীল (মনো বা রটারের সাথে পৃথক হতে পারে)।

সংলগ্ন কেসগুলি ব্যবহার করে আমি আমার মেশিনে আপনার ফলাফলগুলি প্রতিলিপি করেছি:

10 টি ওয়ে স্যুইচ কার্যকর করার জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 25.1383
আনুমানিক সময় প্রতি 10 ওয়ে স্যুইচ (এমএস): 0.00251383

50 টি ওয়ে স্যুইচটি চালানোর জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 26.593
আনুমানিক সময় প্রতি 50 ওয়ে স্যুইচ (এমএস): 0.0026593

5000 ওয়ে স্যুইচটি চালানোর জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 23.7094
আনুমানিক সময় প্রতি 5000 ওয়ে স্যুইচ (এমএস): 0.00237094

50000 ওয়ে স্যুইচটি চালানোর জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 20.0933
আনুমানিক সময় প্রতি 50000 ওয়ে স্যুইচ (এমএস): 0.00200933

তারপরে আমি অ-সংলগ্ন কেস এক্সপ্রেশনগুলিও ব্যবহার করেছি:

10 টি ওয়ে স্যুইচটি চালানোর জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 19.6189
প্রতি 10 ওয়ে স্যুইচ (এমএস) প্রতি আনুমানিক সময়: 0.00196189

500 ওয়ে স্যুইচ কার্যকর করার জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 19.1664
আনুমানিক সময় প্রতি 500 ওয়ে স্যুইচ (এমএস): 0.00191664

5000 ওয়ে স্যুইচটি চালানোর জন্য মোট সময়, 10000 পুনরাবৃত্তি (এমএস): 19.5871
আনুমানিক সময় প্রতি 5000 ওয়ে সুইচ (এমএস): 0.00195871

একটি সংলগ্ন 50,000 কেস সুইচ বিবৃতি সংকলন করবে না।
"'কনসোল অ্যাপ্লিকেশন 1. প্রোগ্রাম.মেন (স্ট্রিং [])' এর নিকটে সংকলনের জন্য একটি এক্সপ্রেশন খুব দীর্ঘ বা জটিল '

এখানে মজার বিষয় হ'ল বাইনারি ট্রি অনুসন্ধানটি সিআইএল স্যুইচ নির্দেশের চেয়ে দ্রুত (সম্ভবত পরিসংখ্যানগতভাবে নয়) প্রদর্শিত হয়।

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

এটি স্ট্রিং পরিস্থিতিকেও সম্বোধন করে না, যেখানে একটি স্ট্যাটিক Generic.Dictionary<string,int32>তৈরি হতে পারে এবং প্রথম ব্যবহারে নির্দিষ্ট ওভারহেড ভোগে। এখানে পারফরম্যান্স এর পারফরম্যান্স উপর নির্ভর করবেGeneric.Dictionary

আপনি যদি সি # ল্যাঙ্গুয়েজ স্পেসিফিকেশন পরীক্ষা করেন (সিআইএল স্পেক নয়) আপনি দেখতে পাবেন "15.7.2" স্যুইচ স্টেটমেন্ট "" ধ্রুবক সময় "সম্পর্কে কোনও উল্লেখ করে না বা অন্তর্নিহিত বাস্তবায়ন এমনকি সিআইএল স্যুইচ নির্দেশিকা ব্যবহার করে (ধরে নিতে খুব সতর্কতা অবলম্বন করুন) এই ধরনের জিনিস).

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


অবশ্যই এই সময়গুলি মেশিন এবং শর্তের উপর নির্ভর করবে। আমি এই সময় সংক্রান্ত পরীক্ষাগুলির দিকে মনোযোগ দেব না, আমরা যে মাইক্রোসেকেন্ডের সময়কালের কথা বলছি তা যে কোনও "আসল" কোড চালিত হওয়ার দ্বারা দ্বিখণ্ডিত হয় (এবং আপনাকে অবশ্যই কিছু "রিয়েল কোড" অন্তর্ভুক্ত করতে হবে অন্যথায় সংকলকটি শাখাটি অপ্টিমাইজ করবে), বা সিস্টেমে জিটার। আমার উত্তরগুলি IL DASM ব্যবহারের উপর ভিত্তি করে সি # সংকলক দ্বারা নির্মিত সিআইএল পরীক্ষা করতে । অবশ্যই এটি চূড়ান্ত নয়, সিপিইউ পরিচালিত প্রকৃত নির্দেশনাগুলি তখন জেআইটি তৈরি করে।

আমি আমার x86 মেশিনে প্রকৃতরূপে নির্ধারিত চূড়ান্ত সিপিইউ নির্দেশাবলী পরীক্ষা করেছি এবং একটি সাধারণ সংলগ্ন সেট সুইচটি এরকম কিছু করে নিশ্চিত করতে পারি:

  jmp     ds:300025F0[eax*4]

যেখানে একটি বাইনারি ট্রি অনুসন্ধান পূর্ণ:

  cmp     ebx, 79Eh
  jg      3000352B
  cmp     ebx, 654h
  jg      300032BB
  
  cmp     ebx, 0F82h
  jz      30005EEE

আপনার পরীক্ষাগুলির ফলাফল আমাকে কিছুটা অবাক করে দিয়েছে। আপনি ব্রায়ানের সাথে নিজেকে বদলেছেন? তার ফলাফলগুলি আকারের সাথে বৃদ্ধি দেখায় যখন আপনার হয় না। আমি কিছু মিস করছি? যাই হোক না কেন, পরিষ্কার জবাবের জন্য ধন্যবাদ।
mweerden

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

23

মনে মনে প্রথম কারণটি আসে তিহাসিক :

যেহেতু বেশিরভাগ সি, সি ++ এবং জাভা প্রোগ্রামাররা এই জাতীয় স্বাধীনতা অর্জন করতে অভ্যস্ত না, তাই তারা তাদের দাবি করে না।

আর একটি, আরও কার্যকর, কারণ ভাষা জটিলতা বৃদ্ধি হবে :

প্রথমত, অবজেক্টগুলির .Equals()সাথে ==অপারেটরের সাথে বা তুলনা করা উচিত ? উভয়ই কিছু ক্ষেত্রে বৈধ। এটি করার জন্য আমাদের কি নতুন সিনট্যাক্স প্রবর্তন করা উচিত? আমাদের কি প্রোগ্রামারকে তাদের নিজস্ব তুলনা পদ্ধতি প্রবর্তন করার অনুমতি দেওয়া উচিত?

তদ্ব্যতীত, বস্তুগুলিতে স্যুইচ করার অনুমতি দেওয়া স্যুইচ বিবৃতি সম্পর্কে অন্তর্নিহিত অনুমানগুলি ভেঙে দেবে । স্যুইচ স্টেটমেন্ট পরিচালিত করার জন্য দুটি নিয়ম রয়েছে যে বস্তুগুলিকে স্যুইচ করার অনুমতি দেওয়া হলে সংকলক প্রয়োগ করতে সক্ষম হবে না ( সি # সংস্করণ 3.0 ভাষার স্পেসিফিকেশন , §8.7.2 দেখুন):

  • স্যুইচ লেবেলের মানগুলি ধ্রুবক
  • স্যুইচ লেবেলের মানগুলি পৃথক (যাতে প্রদত্ত সুইচ-এক্সপ্রেশনটির জন্য কেবলমাত্র একটি স্যুইচ ব্লক নির্বাচন করা যায়)

অনুমানক ক্ষেত্রে এই কোড উদাহরণটি বিবেচনা করুন যে অ-ধ্রুবক ক্ষেত্রে মানগুলি অনুমোদিত ছিল:

void DoIt()
{
    String foo = "bar";
    Switch(foo, foo);
}

void Switch(String val1, String val2)
{
    switch ("bar")
    {
        // The compiler will not know that val1 and val2 are not distinct
        case val1:
            // Is this case block selected?
            break;
        case val2:
            // Or this one?
            break;
        case "bar":
            // Or perhaps this one?
            break;
    }
}

কোডটি কী করবে? যদি মামলার বিবৃতি পুনরায় সাজানো হয় তবে কী হবে? প্রকৃতপক্ষে, সি # স্যুইচ পতনের মাধ্যমে অবৈধভাবে তৈরি করার একটি কারণ হ'ল স্যুইচ বিবৃতিগুলি ইচ্ছামত পুনরায় সাজানো যেতে পারে।

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


2
স্যুইচ পুনঃক্রমের নোট note কেসের কোনও কোড না থাকলে সেই মাধ্যমে পড়াটা আইনী। যেমন, কেস 1: কেস 2: কনসোল.রাইটলাইন ("হাই"); বিরতি;
জোয়েল ম্যাকবেথ

10

যাইহোক, ভিবি, একই অন্তর্নিহিত আর্কিটেকচার থাকার ফলে অনেক বেশি নমনীয় Select Caseবিবৃতি দেয় (উপরের কোডটি ভিবিতে কাজ করবে) এবং এখনও কার্যকর কোড তৈরি করে যেখানে এটি সম্ভব তাই প্রযুক্তিগত বাধা দ্বারা যুক্তিটি সাবধানতার সাথে বিবেচনা করতে হবে।


1
Select Caseস্বীকারোক্তি ভিবি খুবই নমনীয় এবং একটি সুপার সময় বাঁচায় হয়। আমি এটা খুব মিস করছি।
এডুয়ার্ডো মোল্টেনি

@ এডুয়ার্ডো মল্টেনি এফ # তে স্যুইচ করুন। এটি পাসকালের এবং ভিবি'র স্যুইচগুলিকে তুলনায় তুলনামূলকভাবে নির্বোধ বাচ্চাদের মতো করে তোলে।
লুয়ান

10

বেশিরভাগ ক্ষেত্রে, ভাষা ডিজাইনারদের কারণে এই বিধিনিষেধগুলি কার্যকর হয়। অন্তর্নিহিত ন্যায়সঙ্গততা ল্যাঙ্গুঞ্জ ইতিহাস, আদর্শ বা সংকলক ডিজাইনের সরলকরণের সাথে সামঞ্জস্য হতে পারে।

সংকলক চয়ন করতে পারে (এবং করবে):

  • একটি বড় if-অন্য বিবৃতি তৈরি করুন
  • একটি এমএসআইএল স্যুইচ নির্দেশিকা ব্যবহার করুন (জাম্প টেবিল)
  • একটি জেনেরিক তৈরি করুন। অভিধান <স্ট্রিং, ইনট 32>, এটি প্রথম ব্যবহারের জন্য পপুলেট করুন এবং জেনেরিক ডিকোরিয়াস <> :: এমএসআইএল স্যুইচ নির্দেশিকা (জাম্প টেবিল) এ যাওয়ার জন্য একটি সূচীর জন্য ট্রাইগেটভ্যালু () কল করুন Try
  • if-elses এবং MSIL "স্যুইচ" জাম্পের সংমিশ্রণটি ব্যবহার করুন use

স্যুইচ বিবৃতি একটি ধ্রুবক সময় শাখা নয়। সংকলকটি শর্ট-কাটগুলি (হ্যাশ বালতি ইত্যাদি ব্যবহার করে) খুঁজে পেতে পারে তবে আরও জটিল কেসগুলি আরও জটিল এমএসআইএল কোড উত্পন্ন করবে যা কিছু ক্ষেত্রে অন্যদের তুলনায় খুব দ্রুত শাখা প্রকাশিত হবে।

স্ট্রিং কেসটি পরিচালনা করতে, সংকলকটি a.Equals (খ) (এবং সম্ভবত a.GetHashCode ()) ব্যবহার করে (কিছু সময়ে) শেষ হবে will আমি মনে করি যে এই প্রতিবন্ধকতাগুলি সন্তুষ্ট করে এমন কোনও বস্তু ব্যবহার করা সংকলকটির পক্ষে ট্রিভাল হবে।

স্ট্যাটিক কেস এক্সপ্রেশনগুলির প্রয়োজনীয়তার জন্য ... যদি কেস এক্সপ্রেশনগুলি সংজ্ঞাবাদী না হয় তবে সেগুলির কয়েকটি অপটিমাইজেশন (হ্যাশিং, ক্যাশিং ইত্যাদি) উপলভ্য হবে না। তবে আমরা ইতিমধ্যে দেখেছি যে কখনও কখনও সংকলক সরলতাকে বেছে নেয় যদি অন্যথায় রাস্তা যাইহোক ...

সম্পাদনা: লমএক্সএক্স - "টাইপফ" অপারেটর সম্পর্কে আপনার বোঝা সঠিক নয়। "টাইপফ" অপারেটরটি সিস্টেমের জন্য ব্যবহার করা হয় a কোনও প্রকারের জন্য টাইপ অবজেক্ট (এর সুপারটাইপস বা ইন্টারফেসগুলির সাথে কিছুই করার নয়)। প্রদত্ত প্রকারের সাথে কোনও সামগ্রীর রান-টাইম সামঞ্জস্যতা পরীক্ষা করা "অপারেটর" এর কাজ। কোনও বস্তুকে প্রকাশ করতে এখানে "টাইপফ" ব্যবহার অপ্রাসঙ্গিক।


6

বিষয়টিতে থাকাকালীন, জেফ আতউডের মতে, স্যুইচ বিবৃতিটি একটি প্রোগ্রামিং নৃশংসতা । এগুলি অল্প পরিমাণে ব্যবহার করুন।

আপনি প্রায়শই টেবিল ব্যবহার করে একই কাজটি সম্পাদন করতে পারেন। উদাহরণ স্বরূপ:

var table = new Dictionary<Type, string>()
{
   { typeof(int), "it's an int!" }
   { typeof(string), "it's a string!" }
};

Type someType = typeof(int);
Console.WriteLine(table[someType]);

7
আপনি কোনও প্রমাণ সহ কফ টুইটার পোস্ট বন্ধ করে কাউকে গুরুত্বের সাথে উদ্ধৃত করছেন? কমপক্ষে এএ নির্ভরযোগ্য উত্স লিঙ্ক।
ইভান হ্যামিল্টন

4
এটি একটি নির্ভরযোগ্য উত্স থেকে; প্রশ্নে থাকা টুইটার পোস্টটি আপনি খুঁজছেন এমন সাইটের লেখক জেফ আতউডের। :-) আপনি কৌতূহলী হলে এই বিষয়ে জেফের হাতে কয়েকটা ব্লগ পোস্ট রয়েছে।
এহুদা গ্যাব্রিয়েল হিমাঙ্গো

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

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

পুরানো উত্তর / প্রশ্ন, তবে আমি ভাবতাম যে (আমি ভুল হলে আমাকে সংশোধন করি) Dictionaryএকটি অনুকূলিত switchবিবৃতির চেয়ে যথেষ্ট ধীর হয়ে যেত ...?
পল

6

স্যুইচ বিবৃতিটি কেবল স্থিতিশীল বিশ্লেষণের কাছে চলে যাওয়ার কোনও কারণ আমি দেখতে পাচ্ছি না

এটা ঠিক যে, না আছে , এবং অনেক ভাষায় আসলে ব্যবহার গতিশীল সুইচ বিবৃতি না। এর অর্থ তবে এই যে "কেস" ধারাগুলি পুনরায় অর্ডার করা কোডের আচরণ পরিবর্তন করতে পারে।

ডিজাইনের সিদ্ধান্তগুলির পিছনে কিছু আকর্ষণীয় তথ্য রয়েছে যা এখানে "স্যুইচ" এ গেছে: চলেছে: সি # স্যুইচ বিবৃতিটি কেন পতনের মাধ্যমে অনুমতি না দেওয়ার জন্য ডিজাইন করা হয়েছে, তবে এখনও একটি বিরতি প্রয়োজন?

গতিশীল কেস এক্সপ্রেশনগুলিকে মঞ্জুরি দেওয়ার ফলে এই পিএইচপি কোডের মতো নৈরাশ্য হতে পারে:

switch (true) {
    case a == 5:
        ...
        break;
    case b == 10:
        ...
        break;
}

যা স্পষ্টভাবে শুধু if-elseবিবৃতি ব্যবহার করা উচিত ।


1
আমি পিএইচপি সম্পর্কে যা পছন্দ করি (এখন আমি সি # তে রূপান্তর করছি), এটিই স্বাধীনতা।
এটির

5

মাইক্রোসফ্ট অবশেষে শুনেছি!

এখন সি # 7 দিয়ে আপনি করতে পারেন:

switch(shape)
{
case Circle c:
    WriteLine($"circle with radius {c.Radius}");
    break;
case Rectangle s when (s.Length == s.Height):
    WriteLine($"{s.Length} x {s.Height} square");
    break;
case Rectangle r:
    WriteLine($"{r.Length} x {r.Height} rectangle");
    break;
default:
    WriteLine("<unknown shape>");
    break;
case null:
    throw new ArgumentNullException(nameof(shape));
}

3

এটি কোনও কারণ নয়, তবে সি # স্পেসিফিকেশন বিভাগ 8.7.2 এ নিম্নলিখিতটি উল্লেখ করেছে:

একটি স্যুইচ স্টেটমেন্টের পরিচালনার ধরণটি স্যুইচ এক্সপ্রেশন দ্বারা প্রতিষ্ঠিত হয়। যদি স্যুইচ এক্সপ্রেশনের ধরণটি সবাইটি, বাইট, সংক্ষিপ্ত, ushort, int, uint, দীর্ঘ, উলং, চর, স্ট্রিং বা একটি এনাম-টাইপ হয় তবে তা হ'ল স্যুইচ স্টেটমেন্টের পরিচালনা পদ্ধতি। অন্যথায়, ঠিক একজন ব্যবহারকারীর দ্বারা সংজ্ঞায়িত অন্তর্নিহিত রূপান্তর (§6.4) অবশ্যই নীচের সম্ভাব্য প্রশাসনিক ধরণের একটিতে স্যুইচ এক্সপ্রেশনের ধরণ থেকে বিদ্যমান থাকতে হবে: এসবিট, বাইট, সংক্ষিপ্ত, ushort, int, uint, দীর্ঘ, উলং, চর, স্ট্রিং । যদি এরূপ কোনও অন্তর্নিহিত রূপান্তর বিদ্যমান না থাকে, বা যদি এই জাতীয় একাধিক রূপান্তর বিদ্যমান থাকে তবে একটি সংকলন-সময় ত্রুটি ঘটে।

সি # 3.0 স্পেসিফিকেশনটি এখানে অবস্থিত: http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/CSharp%20Language%20Specifications.doc


3

উপরের যিহূদার উত্তর আমাকে একটি ধারণা দিয়েছে। আপনি ওপরের সুইচ ব্যবহারটি উপরে ব্যবহার করে "নকল" করতে পারেন Dictionary<Type, Func<T>:

Dictionary<Type, Func<object, string,  string>> typeTable = new Dictionary<Type, Func<object, string, string>>();
typeTable.Add(typeof(int), (o, s) =>
                    {
                        return string.Format("{0}: {1}", s, o.ToString());
                    });

এটি আপনাকে একই স্টাইলে স্যুইচ স্টেটমেন্টের মতো আচরণের সাথে যুক্ত করতে দেয়। আমি বিশ্বাস করি আইএল-এ সংকলিত হওয়ার সময় এটিতে স্যুইচ-স্টাইলের জাম্প টেবিলের পরিবর্তে কীড হওয়ার অতিরিক্ত সুবিধা রয়েছে।


0

আমি মনে করি যে কম্পাইলারটি আপনার সুইচ বিবৃতিটিকে স্বয়ংক্রিয়ভাবে অনুবাদ করতে পারে না তার কোনও মৌলিক কারণ নেই:

if (t == typeof(int))
{
...
}
elseif (t == typeof(string))
{
...
}
...

কিন্তু এটির দ্বারা খুব বেশি লাভ হয় নি।

অবিচ্ছেদ্য প্রকারভেদে একটি কেস স্টেটমেন্ট সংকলকটিকে অনেকগুলি অনুকূলিতকরণ করতে দেয়:

  1. কোনও সদৃশ নেই (যদি না আপনি কেস লেবেলগুলির অনুলিপি করেন, যা সংকলক সনাক্ত করে)। আপনার উদাহরণে টি উত্তরাধিকারের কারণে একাধিক ধরণের সাথে মেলে। প্রথম ম্যাচটি কার্যকর করা উচিত? তাদের সবাই?

  2. সমস্ত তুলনা এড়ানোর জন্য সংকলক একটি জাম্প টেবিল দ্বারা একটি অবিচ্ছেদ্য টাইপের উপরে একটি সুইচ বিবৃতিটি প্রয়োগ করতে বেছে নিতে পারে। যদি আপনি এমন একটি গণনা পরিবর্তন করে যা এর পূর্ণসংখ্যার মান 0 থেকে 100 হয় তবে এটি এতে 100 পয়েন্টার সহ একটি অ্যারে তৈরি করে, প্রতিটি স্যুইচ স্টেটমেন্টের জন্য একটি করে। রানটাইমের সময় এটি সহজেই অ্যারে থেকে ঠিকানাটি সন্ধান করে পূর্ণসংখ্য মানটি চালু হওয়ার উপর ভিত্তি করে। এটি 100 তুলনা সম্পাদন করার চেয়ে অনেক ভাল রানটাইম পারফরম্যান্সের জন্য তৈরি করে।


1
এখানে খেয়াল করা একটি গুরুত্বপূর্ণ জটিলতা যে .NET মেমরি মডেল নির্দিষ্ট শক্তিশালী গ্যারান্টী যে আপনার pseudocode হয় অবিকল (প্রকল্পিত, অবৈধ সমতূল্য না করতে হয়েছে সি # ) switch (t) { case typeof(int): ... }কারণ আপনার অনুবাদ যে বোঝা পরিবর্তনশীল t নয় দুইবার যদি মেমরি থেকে সংগৃহীত হতে t != typeof(int), যেহেতু আধুনিক would (putatively) সর্বদা t ঠিক একবার পড়ুন । এই পার্থক্যটি সমকালীন কোডের সঠিকতা ভঙ্গ করতে পারে যা এই দুর্দান্ত গ্যারান্টির উপর নির্ভর করে। এ সম্পর্কে আরও তথ্যের জন্য, জো ডাফির উইন্ডোজে সমকালীন প্রোগ্রামিং দেখুন
গ্লেন স্লেডেন

0

স্যুইচ স্টেটমেন্ট ডকুমেন্টেশন অনুসারে যদি অবজেক্টকে একটি অবিচ্ছেদ্য প্রকারে স্পষ্টভাবে রূপান্তর করার কোনও দ্ব্যর্থহীন উপায় থাকে তবে তা অনুমোদিত হবে। আমি মনে করি আপনি এমন আচরণের প্রত্যাশা করছেন যেখানে প্রতিটি কেস স্টেটমেন্টের সাথে এটি প্রতিস্থাপন করা if (t == typeof(int))হবে তবে আপনি যখন অপারেটরটিকে ওভারলোড করতে পারেন তখন এটি কীটপতঙ্গগুলির পুরো ক্যান খুলবে। আপনি যদি নিজের == ওভাররাইড ভুলভাবে লিখেছিলেন তবে স্যুইচ বিবৃতিটির বাস্তবায়নের বিশদটি পরিবর্তিত হলে আচরণটি পরিবর্তিত হবে। ইন্টিগ্রাল টাইপ এবং স্ট্রিং এবং যে জিনিসগুলি অবিচ্ছেদ্য প্রকারে হ্রাস করা যায় (এবং উদ্দেশ্যে করা হয়) এর সাথে তুলনা কমিয়ে তারা সম্ভাব্য সমস্যাগুলি এড়িয়ে চলে।


0

লিখেছেন:

"আপনার যত মামলা আছে তা বিবেচনা না করেই স্যুইচ বিবৃতি একটি ধ্রুবক সময় শাখা করে does"

যেহেতু ভাষাটি স্ট্রিং টাইপটিকে একটি স্যুইচ বিবৃতিতে ব্যবহার করার অনুমতি দেয় আমি ধারণা করি যে সংকলক এই ধরণের জন্য একটি ধ্রুবক সময় শাখা বাস্তবায়নের জন্য কোড উত্পন্ন করতে অক্ষম এবং যদি তবে-পরে শৈলী তৈরি করা প্রয়োজন।

@ এমওয়েরডেন - আহ আমি দেখছি ধন্যবাদ।

সি # এবং। নেট সম্পর্কে আমার প্রচুর অভিজ্ঞতা নেই তবে এটি মনে হয় যে ভাষা নকশাকারীরা সংকীর্ণ পরিস্থিতিতে বাদে টাইপ সিস্টেমে স্থির অ্যাক্সেসের অনুমতি দেয় না। Typeof শব্দ একটি বস্তু ফেরৎ তাই এই রান-টাইম শুধুমাত্র এ প্রবেশযোগ্য।


0

আমি মনে করি হেনক এটিকে "টাইপ সিস্টেমে স্ট্যাট্যাটিক অ্যাক্সেস নেই" জিনিসটি দিয়ে পেরেক দিয়েছিল

অন্য বিকল্পটি হ'ল এমন সংখ্যার কোনও অর্ডার নেই যেখানে সংখ্যা এবং স্ট্রিং হতে পারে। সুতরাং একটি টাইপ স্যুইচ একটি বাইনারি অনুসন্ধান ট্রি তৈরি করতে পারে না, কেবল একটি লিনিয়ার অনুসন্ধান search


0

আমি এই মন্তব্যে একমত যে টেবিল চালিত পদ্ধতির ব্যবহার প্রায়শই ভাল।

সি # 1.0 এ এটি সম্ভব ছিল না কারণ এতে জেনারিক এবং বেনামে প্রতিনিধি ছিল না। সি # এর নতুন সংস্করণগুলিতে এই কাজটি করার জন্য ভাস্কর্য রয়েছে। বস্তুর আক্ষরিক জন্য একটি স্বরলিপি থাকাও সহায়তা করে।


0

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

কড়া কথায় বলতে গেলে আপনি একেবারেই ঠিক বলেছেন যে এই নিষেধাজ্ঞাগুলি লাগানোর কোনও কারণ নেই। কেউ সন্দেহ করতে পারে যে এর কারণ হ'ল অনুমতিপ্রাপ্ত মামলার জন্য বাস্তবায়ন খুব দক্ষ (যেমন ব্রায়ান এনসিংক ( ৪৯৯২১ ) প্রস্তাবিত ) তবে আমি সন্দেহ করি বাস্তবায়নটি খুব দক্ষ (যদি বিবৃতি দেওয়া হয়) আমি যদি পূর্ণসংখ্যার এবং কিছু এলোমেলো ক্ষেত্রে ব্যবহার করি তবে (যেমন 345, -4574 এবং 1234203)। এবং যে কোনও ক্ষেত্রে, এটির জন্য (বা কমপক্ষে আরও বেশি) অনুমতি দেওয়ার ক্ষেত্রে কী ক্ষতি এবং এটি নির্দিষ্ট সুনির্দিষ্ট ক্ষেত্রে (যেমন (প্রায়) একটানা সংখ্যার জন্য) কেবল দক্ষ, তা বলে।

তবে আমি ধারণা করতে পারি যে লোমাএক্সএক্স ( 44918 ) প্রদত্ত কারণের কারণে কেউ প্রকারগুলি বাদ দিতে চায় want

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


0

সি # 8 আপনাকে একটি স্যুইচ এক্সপ্রেশন ব্যবহার করে এই সমস্যাটি মার্জিতভাবে এবং নিখুঁতভাবে সমাধান করার অনুমতি দেয়:

public string GetTypeName(object obj)
{
    return obj switch
    {
        int i => "Int32",
        string s => "String",
        { } => "Unknown",
        _ => throw new ArgumentNullException(nameof(obj))
    };
}

ফলস্বরূপ, আপনি পাবেন:

Console.WriteLine(GetTypeName(obj: 1));           // Int32
Console.WriteLine(GetTypeName(obj: "string"));    // String
Console.WriteLine(GetTypeName(obj: 1.2));         // Unknown
Console.WriteLine(GetTypeName(obj: null));        // System.ArgumentNullException

আপনি এখানে নতুন বৈশিষ্ট্য সম্পর্কে আরও পড়তে পারেন ।

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