নতুন অবজেক্টকে নির্ধারিত করার সময় স্যুইচ বা একটি অভিধান


12

সম্প্রতি, আমি বিবৃতিগুলির Dictionariesপরিবর্তে 1-1 টি সম্পর্ককে ম্যাপিংয়ে অগ্রাধিকার দিতে এসেছি Switch। আমি এটি লেখার জন্য আরও দ্রুত এবং মানসিকভাবে প্রক্রিয়া করা সহজ বলে মনে করি। দুর্ভাগ্যক্রমে, যখন কোনও সামগ্রীর নতুন উদাহরণে ম্যাপিং করা হচ্ছে তখন আমি এটিকে সংজ্ঞায়িত করতে চাই না:

var fooDict = new Dictionary<int, IBigObject>()
{
    { 0, new Foo() }, // Creates an instance of Foo
    { 1, new Bar() }, // Creates an instance of Bar
    { 2, new Baz() }  // Creates an instance of Baz
}

var quux = fooDict[0]; // quux references Foo

এই কনস্ট্রাক্টটি দেওয়া হয়েছে, আমি সিপিইউ চক্র এবং মেমরিটি 3 টি অবজেক্ট তৈরি করে নষ্ট করেছি, তাদের নির্মাণকারীরা যা কিছু করতে পারে তা করছে এবং কেবল তার মধ্যে একটি ব্যবহার করে শেষ করেছি। আমি আরও বিশ্বাস করি যে fooDict[0]এই ক্ষেত্রে অন্যান্য অবজেক্টগুলিকে ম্যাপিংয়ের ফলে তাদের Fooউদ্দেশ্য হিসাবে কোনও নতুন উদাহরণ তৈরি করার পরিবর্তে একই জিনিসটিকে রেফারেন্স করতে হবে । পরিবর্তে ল্যাম্বডা ব্যবহার করার একটি সমাধান হ'ল:

var fooDict = new Dictionary<int, Func<IBigObject>>()
{
    { 0, () => new Foo() }, // Returns a new instance of Foo when invoked
    { 1, () => new Bar() }, // Ditto Bar
    { 2, () => new Baz() }  // Ditto Baz
}

var quux = fooDict[0](); // equivalent to saying 'var quux = new Foo();'

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

IBigObject quux;
switch(someInt)
{
    case 0: quux = new Foo(); break;
    case 1: quux = new Bar(); break;
    case 2: quux = new Baz(); break;
}

কোন প্রার্থনা বেশি গ্রহণযোগ্য?

  • দ্রুত অনুসন্ধান এবং কম কীওয়ার্ডের জন্য অভিধান (কেস এবং ব্রেক)
  • স্যুইচ করুন: কোডে আরও সাধারণত পাওয়া যায়, ইন্ডিরিয়ারেশনের জন্য একটি ফানক <> অবজেক্টের প্রয়োজন হয় না।

2
ল্যাম্বডা ব্যতীত আপনি প্রতি বার একই কী (যেমন হিসাবে fooDict[0] is fooDict[0]) দিয়ে অনুসন্ধান করবেন তখন একই দশা ফিরে আসবে । ল্যাম্বডা এবং স্যুইচ উভয়ই এটির ক্ষেত্রে নয়
রাচেট ফ্রিক

@ratchetfreak হ্যাঁ, উদাহরণটি টাইপ করার সময় আমি আসলে এটি উপলব্ধি করেছিলাম। আমি মনে করি আমি এটির একটি নোট কোথাও তৈরি করেছি।
কেচালোক্স

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

উত্তর:


7

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

সিপিইউ চক্র সম্পর্কে আপনার প্রশ্নের উদ্বেগকে আমি এড়িয়ে যাচ্ছি কারণ আপনি মন্তব্যে উল্লেখ করেছেন যে নন-ল্যাম্বডা পদ্ধতির আপনার প্রয়োজনটি সরবরাহ করে না।

আমি মনে করি উভয় পদ্ধতির (সুইচ বনাম অভিধান + ল্যাম্বদা) ভাল হতে চলেছে fine একমাত্র সীমাবদ্ধতা হ'ল অভিধানটি ব্যবহার করে, আপনি ফিরে আসা ক্লাসটি তৈরি করতে যে ধরণের ইনপুট পেতে পারেন তা সীমাবদ্ধ করছেন।

একটি স্যুইচ স্টেটমেন্ট ব্যবহার আপনাকে ইনপুট পরামিতিগুলিতে আরও নমনীয়তা সরবরাহ করবে। তবে এটি যদি কোনও সমস্যা হয়ে থাকে, আপনি কোনও পদ্ধতির ভিতরে অভিধানটি মোড়ানো করতে পারেন এবং একই ফলাফল হতে পারে।

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


দুর্ভাগ্যক্রমে, প্রায় এক মাস আগের হিসাবে, আমার দলটি কেবলমাত্র আমার (লিড ছাড়তে) নিয়ে গঠিত। আমি কারখানার প্যাটার্নের সাথে এর প্রাসঙ্গিকতার কথা ভাবি নি। আসলে এটি একটি ঝরঝরে পর্যবেক্ষণ।
কেচালোক্স

1
@ ক্যালহাক্স: অবশ্যই, আপনি যদি কেবল কারখানার পদ্ধতি পদ্ধতি ব্যবহার করছিলেন তবে আপনার case 0: quux = new Foo(); break;হয়ে ওঠে case 0: return new Foo();যা লেখার পক্ষে খুব সহজ এবং পড়ার চেয়ে সহজ{ 0, () => new Foo() }
পিডিআর

@ পিডিআর এটি কোডে ইতিমধ্যে কয়েকটি জায়গা দেখানো হয়েছে। এই প্রশ্নটি অনুপ্রাণিত করে এমন কোনও বিষয়ে কারখানার পদ্ধতি তৈরির পক্ষে যুক্তিসঙ্গত কারণ সম্ভবত রয়েছে, তবে আমি বুঝতে পেরেছিলাম যে এটির নিজের থেকে জিজ্ঞাসা করা যথেষ্ট আকর্ষণীয় ছিল was
কেচালোক্স

1
@ ক্যালহাক্স: আমি স্বীকার করছি যে আমি একটি অভিধানে স্যুইচ / কেস প্রতিস্থাপনের বিষয়ে সাম্প্রতিক আবেগ সম্পর্কে আগ্রহী নই। আমি এখনও এমন কোনও মামলা দেখিনি যেখানে তার নিজস্ব পদ্ধতিতে স্যুইচকে সরলকরণ এবং পৃথক করা আরও কার্যকর হত না।
পিডিআর

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

7

সি # 4.0 আপনাকে Lazy<T>ক্লাস দেয় যা আপনার নিজস্ব দ্বিতীয় সমাধানের মতো, তবে "অলস সূচনা" আরও স্পষ্টভাবে উচ্চারণ করে।

var fooDict = new Dictionary<int, Lazy<IBigObject>>()
{
    { 0, new Lazy(() => new Foo()) }, // Returns a new instance of Foo when invoked
    { 1, new Lazy(() => new Bar()) }, // Ditto Bar
    { 2, new Lazy(() => new Baz()) }  // Ditto Baz
}

ওহ, আমি জানি না।
কেচালাক্স

ওহ, দুর্দান্ত!
লরেন্ট বোর্গোল্ট-রায়

2
যাইহোক, একবার অলস.ভ্যালুটি অনুরোধ করা হলে, এটি তার জীবদ্দশায় একই উদাহরণ ব্যবহার করে। অলস সূচনা
ড্যান লিয়ন্স

অবশ্যই, অন্যথায় এটি অলস সূচনা হবে না, কেবল প্রতিবার পুনরায় সূচনা।
অব্নার শাহর-কাশতান

ওপিতে বলা হয়েছে যে প্রতিবার নতুন উদাহরণ তৈরি করার জন্য তার এটির প্রয়োজন। লাম্বডাসের সাথে দ্বিতীয় সমাধান এবং একটি স্যুইচ সহ তৃতীয় সমাধান উভয় এটি করে, যখন প্রথম সমাধান এবং অলস <টি> বাস্তবায়ন হয় না।
ড্যান লিয়নস

2

স্টাইলিস্টিকভাবে আমি মনে করি পাঠ্যতা তাদের মধ্যে সমান। এর সাথে নির্ভরতা ইনজেকশন করা সহজ Dictionary

ভুলে যাবেন না যে আপনি কীটি ব্যবহার করার সময় কীটি উপস্থিত আছে কিনা তা অবশ্যই পরীক্ষা করতে হবে Dictionaryএবং যদি তা না দেয় তবে অবশ্যই একটি ফালব্যাক সরবরাহ করতে হবে।

আমি switchস্ট্যাটিক কোড পাথ এবং Dictionaryগতিশীল কোড পাথের জন্য বিবরণটি পছন্দ করব (যেখানে আপনি এন্ট্রি যুক্ত করতে বা সরিয়ে দিতে পারেন)। সংকলকটি switchএটির সাথে না পারায় কিছু স্থিতিশীল অপ্টিমাইজেশন সম্পাদন করতে সক্ষম হতে পারে Dictionary

মজার বিষয় হল, এই Dictionaryপ্যাটার্নটি পাইথনে লোকেরা মাঝে মধ্যে যা করে, কারণ পাইথনের switchবিবৃতি নেই। অন্যথায় তারা যদি-অন্য চেইন ব্যবহার করে।


1

সাধারণভাবে, আমি উভয়ই পছন্দ করব না।

এটি যেটি গ্রহণ করছে এটির সাথে কাজ করা উচিত Func<int, IBigObject>। তারপরে আপনার ম্যাপিংয়ের উত্স একটি অভিধান বা একটি পদ্ধতি হতে পারে যা একটি স্যুইচ স্টেটমেন্ট বা একটি ওয়েব পরিষেবা কল বা কিছু ফাইল লুক ... যা কিছু হোক।

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

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