এটি একটি সাধারণ প্রশ্ন (তবে আমি সি # ব্যবহার করছি), সর্বোত্তম উপায় (সেরা অনুশীলন) কোনটি, আপনি কি কোনও পদ্ধতির জন্য শূন্য বা খালি সংগ্রহ ফেরতের ধরণ হিসাবে সংগ্রহ করেন?
এটি একটি সাধারণ প্রশ্ন (তবে আমি সি # ব্যবহার করছি), সর্বোত্তম উপায় (সেরা অনুশীলন) কোনটি, আপনি কি কোনও পদ্ধতির জন্য শূন্য বা খালি সংগ্রহ ফেরতের ধরণ হিসাবে সংগ্রহ করেন?
উত্তর:
খালি সংগ্রহ সর্বদা.
এটি স্তন্যপান:
if(myInstance.CollectionProperty != null)
{
foreach(var item in myInstance.CollectionProperty)
/* arrgh */
}
null
সংগ্রহ বা গণনা ফিরিয়ে দেওয়ার সময় এটি কখনই ফিরে না আসা সেরা অভ্যাস হিসাবে বিবেচিত হয় । সর্বদা একটি খালি গণ্য / সংগ্রহ ফিরিয়ে দেয়। এটি পূর্বোক্ত বাজে কথাগুলি বাধা দেয় এবং আপনার গাড়িটি আপনার ক্লাসের সহকর্মী এবং ব্যবহারকারীদের দ্বারা উত্সাহিত হতে বাধা দেয়।
বৈশিষ্ট্য সম্পর্কে কথা বলার সময়, সর্বদা আপনার সম্পত্তি একবার সেট করুন এবং এটি ভুলে যান
public List<Foo> Foos {public get; private set;}
public Bar() { Foos = new List<Foo>(); }
নেট 4.6.1 এ আপনি এটিকে অনেকটা ঘনীভূত করতে পারেন:
public List<Foo> Foos { get; } = new List<Foo>();
এমন পদ্ধতিগুলির বিষয়ে কথা বলার সময় যেগুলি পরিগণিতগুলি ফিরে আসে, আপনি সহজেই এর পরিবর্তে একটি খালি গণনা ফিরিয়ে দিতে পারেন null
...
public IEnumerable<Foo> GetMyFoos()
{
return InnerGetFoos() ?? Enumerable.Empty<Foo>();
}
ব্যবহারকে Enumerable.Empty<T>()
ফিরে আসার চেয়ে আরও দক্ষ হিসাবে দেখা যায়, উদাহরণস্বরূপ, একটি নতুন খালি সংগ্রহ বা অ্যারে।
IEnumerable
বা ICollection
না। যাইহোক, আপনি যদি টাইপের কিছু নির্বাচন করেন ICollection
তারাও ফিরে আসে null
... আমি তাদের একটি খালি সংগ্রহ ফিরিয়ে দিতে চাই, তবে আমি তাদের মধ্যে ফিরতে ছুটে এসেছি null
, তাই আমি ভেবেছিলাম যে আমি এটি এখানে উল্লেখ করব। আমি বলব গণনার সংকলনের ডিফল্টটি খালি নয় not আমি জানতাম না যে এটি এতটা সংবেদনশীল বিষয়।
থেকে ফ্রেমওয়ার্ক ডিজাইন নির্দেশিকা 2nd সংস্করণ (PG 256।):
সংগ্রহের বৈশিষ্ট্যগুলি থেকে বা সংগ্রহগুলি ফেরত দেওয়ার পদ্ধতিগুলি থেকে নাল মানগুলি ফেরৎ দেবেন না। পরিবর্তে একটি খালি সংগ্রহ বা একটি খালি অ্যারে ফিরুন।
নাল না ফেরার উপকারিতা সম্পর্কে এখানে একটি আরও আকর্ষণীয় নিবন্ধ (ব্র্যাড আব্রামের ব্লগে আমি কিছু খুঁজে পাওয়ার চেষ্টা করছিলাম, এবং তিনি নিবন্ধটির সাথে যুক্ত ছিলেন)।
সম্পাদনা- যেমন এরিক লিপার্ট এখন মূল প্রশ্নের সাথে মন্তব্য করেছেন, আমিও তাঁর চমৎকার নিবন্ধটি লিঙ্ক করতে চাই ।
আপনার চুক্তি এবং আপনার কংক্রিট কেসের উপর নির্ভর করে । সাধারণত খালি সংগ্রহগুলি ফিরিয়ে দেওয়া ভাল তবে কখনও কখনও ( খুব কম ):
null
আরও নির্দিষ্ট কিছু বোঝাতে পারে;null
।কিছু দৃ concrete় উদাহরণ:
null
উপাদানটির অনুপস্থিতির অর্থ হ'ল, যখন একটি খালি সংগ্রহের ফলে অতিরিক্ত কাজ হবে (এবং সম্ভবত ভুল)<collection />
আরও একটি বিষয় রয়েছে যা এখনও উল্লেখ করা হয়নি। নিম্নলিখিত কোড বিবেচনা করুন:
public static IEnumerable<string> GetFavoriteEmoSongs()
{
yield break;
}
সি # ভাষা এই পদ্ধতিতে কল করার সময় একটি খালি শনাক্তকারীকে ফিরিয়ে দেবে। অতএব, ভাষা নকশা (এবং এইভাবে, প্রোগ্রামার প্রত্যাশা) সাথে সংহত হওয়ার জন্য একটি খালি সংগ্রহ ফিরিয়ে আনা উচিত।
খালি অনেক বেশি গ্রাহক বান্ধব।
একটি খালি গণ্য করার একটি পরিষ্কার পদ্ধতি রয়েছে:
Enumerable.Empty<Element>()
আমার কাছে মনে হচ্ছে আপনার প্রসঙ্গে সিঁথিতে সঠিকভাবে মানটি দেওয়া উচিত, যা কিছু হোক না কেন। একটি নিয়ম যা "সর্বদা একটি খালি সংগ্রহ ফিরিয়ে দেয়" বলে আমার কাছে কিছুটা সরল মনে হয়।
ধরুন, বলুন, কোনও হাসপাতালের জন্য একটি সিস্টেম, আমাদের একটি ফাংশন রয়েছে যা বিগত 5 বছরের জন্য পূর্ববর্তী সমস্ত হাসপাতালে ভর্তির একটি তালিকা ফেরত দেবে বলে মনে করা হচ্ছে। গ্রাহক যদি হাসপাতালে না থাকেন তবে খালি তালিকাটি ফিরিয়ে দেওয়া ভাল বুদ্ধিমান। কিন্তু যদি গ্রাহক ভর্তির ফর্মের সেই অংশটি ফাঁকা রেখে যায়? "খালি তালিকা" "উত্তর নেই" বা "জানি না" থেকে আলাদা করার জন্য আমাদের আলাদা মান দরকার। আমরা একটি ব্যতিক্রম ছুঁড়ে ফেলতে পারি, তবে এটি অগত্যা কোনও ত্রুটির শর্ত নয় এবং এটি অবশ্যই আমাদের সাধারণ প্রোগ্রাম প্রবাহ থেকে দূরে সরিয়ে দেয় না।
আমি প্রায়শই এমন সিস্টেমগুলি দ্বারা হতাশ হয়ে পড়েছি যা শূন্য এবং কোনও উত্তরের মধ্যে পার্থক্য করতে পারে না। আমি বেশ কয়েকবার এসেছি যেখানে কোনও সিস্টেম আমাকে কিছু নম্বর লিখতে বলেছে, আমি শূন্য লিখি এবং আমি একটি ত্রুটি বার্তা পাই যা আমাকে বলছে যে আমাকে অবশ্যই এই ক্ষেত্রে একটি মান লিখতে হবে। আমি সবেমাত্র করেছি: আমি শূন্য প্রবেশ করলাম! তবে এটি শূন্য গ্রহণ করবে না কারণ এটি কোনও উত্তর থেকে আলাদা করতে পারে না।
স্যান্ডার্সকে উত্তর দিন:
হ্যাঁ, আমি ধরে নিচ্ছি যে "ব্যক্তি প্রশ্নের উত্তর দেয়নি" এবং "উত্তরটি শূন্য ছিল" মধ্যে পার্থক্য রয়েছে। এটি ছিল আমার উত্তরের শেষ অনুচ্ছেদের পয়েন্ট। অনেক প্রোগ্রাম ফাঁকা বা শূন্য থেকে "জানেন না" পার্থক্য করতে অক্ষম, যা আমার কাছে একটি সম্ভাব্য গুরুতর ত্রুটি বলে মনে হয়। উদাহরণস্বরূপ, আমি এক বছর বা তারও আগে একটি বাড়ির জন্য কেনাকাটা করছিলাম। আমি একটি রিয়েল এস্টেটের ওয়েবসাইটে গিয়েছিলাম এবং সেখানে অনেকগুলি ঘর জিজ্ঞাসিত মূল্যের সাথে তালিকাবদ্ধ ছিল। 0। আমার কাছে বেশ ভালো লাগছে: তারা এই বাড়িগুলি বিনামূল্যে দিয়ে দিচ্ছে! তবে আমি নিশ্চিত যে দুঃখজনক বাস্তবতা হ'ল তারা কেবল দামটি প্রবেশ করেনি। সেক্ষেত্রে আপনি বলতে পারেন, "ঠিক আছে, অবিশ্বাস্য শূন্যের অর্থ তারা দাম প্রবেশ করেনি - কেউ বাড়ি বিনা দামে দিতে যাচ্ছে না।" তবে সাইটটি বিভিন্ন শহরে গড় জিজ্ঞাসা ও বিক্রয়কৃত তালিকাও তালিকাভুক্ত করেছে। আমি সাহায্য করতে পারছি না কিন্তু অবাক হতে পারি যদি গড়টি শূন্যগুলিকে অন্তর্ভুক্ত না করে, তবে এটি কিছু জায়গার জন্য ভুলভাবে নিম্নতর গড় দেয়। অর্থাত্ $ ১০,০০,০০০ এর গড় কি; $ 120,000; এবং "জানেন না"? প্রযুক্তিগতভাবে উত্তরটি "জানেন না"। আমরা সম্ভবত যা দেখতে চাই তা হল 110,000 ডলার। তবে আমরা যা পাব তা সম্ভবত $ 73,333, যা সম্পূর্ণ ভুল হবে। এছাড়াও, যদি এমন কোনও সাইটে আমাদের যদি সমস্যা হয় যেখানে ব্যবহারকারীরা অন-লাইনে অর্ডার করতে পারেন? (রিয়েল এস্টেটের পক্ষে অসদৃশ্য নয়, তবে আমি নিশ্চিত যে আপনি এটি অন্যান্য অনেক পণ্যগুলির জন্যই সম্পন্ন করেছেন)) আমরা কী "সত্যই এখনও নির্দিষ্ট না করে" "বিনামূল্যে" হিসাবে ব্যাখ্যা করার জন্য চাই? এইভাবে কিছু জায়গার জন্য ভুলভাবে নিম্ন গড় দেওয়া। অর্থাত্ $ ১০,০০,০০০ এর গড় কি; $ 120,000; এবং "জানেন না"? প্রযুক্তিগতভাবে উত্তরটি "জানেন না"। আমরা সম্ভবত যা দেখতে চাই তা হল 110,000 ডলার। তবে আমরা যা পাব তা সম্ভবত $ 73,333, যা সম্পূর্ণ ভুল হবে। এছাড়াও, যদি এমন কোনও সাইটে আমাদের যদি সমস্যা হয় যেখানে ব্যবহারকারীরা অন-লাইনে অর্ডার করতে পারেন? (রিয়েল এস্টেটের পক্ষে অসদৃশ্য নয়, তবে আমি নিশ্চিত যে আপনি এটি অন্যান্য অনেক পণ্যগুলির জন্যই সম্পন্ন করেছেন)) আমরা কী "সত্যই এখনও নির্দিষ্ট না করে" "বিনামূল্যে" হিসাবে ব্যাখ্যা করার জন্য চাই? এইভাবে কিছু জায়গার জন্য ভুলভাবে নিম্ন গড় দেওয়া। অর্থাত্ $ ১০,০০,০০০ এর গড় কি; $ 120,000; এবং "জানেন না"? প্রযুক্তিগতভাবে উত্তরটি "জানেন না"। আমরা সম্ভবত যা দেখতে চাই তা হল 110,000 ডলার। তবে আমরা যা পাব তা সম্ভবত $ 73,333, যা সম্পূর্ণ ভুল হবে। এছাড়াও, যদি এমন কোনও সাইটে আমাদের যদি সমস্যা হয় যেখানে ব্যবহারকারীরা অন-লাইনে অর্ডার করতে পারেন? (রিয়েল এস্টেটের পক্ষে অসদৃশ্য নয়, তবে আমি নিশ্চিত যে আপনি এটি অন্যান্য অনেক পণ্যগুলির জন্যই সম্পন্ন করেছেন)) আমরা কী "সত্যই এখনও নির্দিষ্ট না করে" "বিনামূল্যে" হিসাবে ব্যাখ্যা করার জন্য চাই? যা পুরোপুরি ভুল হবে। এছাড়াও, যদি এমন কোনও সাইটে আমাদের যদি সমস্যা হয় যেখানে ব্যবহারকারীরা অন-লাইনে অর্ডার করতে পারেন? (রিয়েল এস্টেটের পক্ষে অসদৃশ্য নয়, তবে আমি নিশ্চিত যে আপনি এটি অন্যান্য অনেক পণ্যগুলির জন্যই সম্পন্ন করেছেন)) আমরা কী "সত্যই এখনও নির্দিষ্ট না করে" "বিনামূল্যে" হিসাবে ব্যাখ্যা করার জন্য চাই? যা পুরোপুরি ভুল হবে। এছাড়াও, যদি এমন কোনও সাইটে আমাদের যদি সমস্যা হয় যেখানে ব্যবহারকারীরা অন-লাইনে অর্ডার করতে পারেন? (রিয়েল এস্টেটের পক্ষে অসদৃশ্য নয়, তবে আমি নিশ্চিত যে আপনি এটি অন্যান্য অনেক পণ্যগুলির জন্যই সম্পন্ন করেছেন)) আমরা কী "সত্যই এখনও নির্দিষ্ট না করে" "বিনামূল্যে" হিসাবে ব্যাখ্যা করার জন্য চাই?
আরআর দুটি পৃথক ফাংশন করছে, একটি "আছে কি?" এবং একটি "যদি তাই হয় তবে এটি কী?" হ্যাঁ, আপনি অবশ্যই এটি করতে পারতেন তবে আপনি কেন চান? এখন কলিং প্রোগ্রামটি একের পরিবর্তে দুটি কল করতে হবে। যদি কোনও প্রোগ্রামার "কোনটি" কল করতে ব্যর্থ হয় তবে কী হবে? এবং সরাসরি "এটি কি?" ? প্রোগ্রামটি কি একটি ভুল নেতৃত্বের শূন্য ফিরে পাবে? একটি ব্যতিক্রম নিক্ষেপ? একটি অপরিবর্তিত মান ফেরত দেবেন? এটি আরও কোড, আরও কাজ এবং আরও সম্ভাব্য ত্রুটি তৈরি করে।
আমি দেখতে পাচ্ছি কেবলমাত্র এটি হ'ল এটি আপনাকে একটি স্বেচ্ছাসেবী বিধি মেনে চলতে সক্ষম করে। এই নিয়মের কোনও সুবিধা রয়েছে যা এটি মান্য করার সমস্যাকে মূল্য দেয়? তা না হলে কেন বিরক্ত করবেন?
জ্যামাইক্যাক্সকে উত্তর দিন:
আসল কোডটি কেমন হবে তা বিবেচনা করুন। আমি জানি প্রশ্নটি সি # বলেছে তবে আমি জাভা লিখলে ক্ষমা করবেন। আমার সি # খুব তীক্ষ্ণ নয় এবং নীতিটি একই।
শূন্য রিটার্ন সহ:
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
একটি পৃথক ফাংশন সহ:
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
এটি নাল রিটার্ন সহ একটি লাইন বা দুটি কম কোড, সুতরাং এটি কলারের উপর বেশি বোঝা নয়, এটি কম।
আমি দেখতে পাচ্ছি না এটি কীভাবে একটি ডিআরওয়াই ইস্যু তৈরি করে। আমাদের দু'বার কল কার্যকর করতে হবে এমনটি নয়। যদি তালিকাটি উপস্থিত না থাকে আমরা যদি সর্বদা একই কাজটি করতে চাইতাম, সম্ভবত আমরা কলারটি না করে গেট-লিস্টের কার্যক্রমে হ্যান্ডলিংকে চাপ দিতে পারতাম এবং সুতরাং কলারে কোডটি রাখা একটি ডিআরওয়াই লঙ্ঘন হবে। তবে আমরা অবশ্যই অবশ্যই সর্বদা একই জিনিস করতে চাই না। প্রক্রিয়াজাতকরণের জন্য আমাদের অবশ্যই তালিকা থাকতে হবে এমন ফাংশনগুলিতে, একটি অনুপস্থিত তালিকা এমন একটি ত্রুটি যা প্রসেসিংয়ে ভালভাবে থামতে পারে। তবে কোনও সম্পাদনা স্ক্রিনে, তারা অবশ্যই ডেটা প্রবেশ না করায় আমরা অবশ্যই প্রক্রিয়াজাতকরণ থামাতে চাই না: আমরা তাদের ডেটা প্রবেশ করতে দিতে চাই। সুতরাং "কোনও তালিকা নয়" হ্যান্ডলিং কলার পর্যায়ে এক বা অন্য কোনও উপায়ে করতে হবে। এবং আমরা নাল রিটার্ন বা পৃথক ফাংশন দিয়ে তা করি কিনা তা বড় নীতিটির কোনও পার্থক্য করে না।
অবশ্যই, যদি কলার শূন্য অনুসন্ধান না করে তবে প্রোগ্রামটি নাল পয়েন্টার ব্যতিক্রম সহ ব্যর্থ হতে পারে। তবে যদি আলাদাভাবে "কোনও" পেয়ে থাকে এবং কলকারী সেই ফাংশনটিকে কল করে না তবে অন্ধভাবে "get list" ফাংশনটি কল করে তবে কী ঘটে? যদি এটি একটি ব্যতিক্রম ছুঁড়ে দেয় বা অন্যথায় ব্যর্থ হয় তবে ভাল, এটি যদি নালায় ফিরে আসে এবং এটির জন্য পরীক্ষা না করে তবে যা ঘটেছিল তা অনেকটাই একই। যদি এটি একটি খালি তালিকা দেয় তবে এটি কেবল ভুল। আপনি "শূন্য উপাদানগুলির সাথে আমার একটি তালিকা আছে" এবং "আমার একটি তালিকা নেই" এর মধ্যে পার্থক্য করতে ব্যর্থ হচ্ছেন। এটি ব্যবহারকারী যখন কোনও দাম প্রবেশ করায় না, তখন দামের জন্য শূন্য ফিরিয়ে দেওয়ার মতো: এটি কেবল ভুল।
সংগ্রহের অতিরিক্ত বৈশিষ্ট্য সংযুক্তি কীভাবে সহায়তা করে তা আমি দেখতে পাচ্ছি না। কলারের এখনও এটি পরীক্ষা করে দেখতে হবে। নাল পরীক্ষা করার চেয়ে এটি কীভাবে ভাল? আবার, ঘটতে পারে এমন চূড়ান্ত সবচেয়ে খারাপ ঘটনাটি হ'ল প্রোগ্রামার এটি পরীক্ষা করে ভুলে যাওয়া এবং ভুল ফলাফল দেয়।
কোনও ফাংশন যা নালকে প্রত্যাবর্তন করে তা যদি প্রোগ্রামার নাল অর্থ "একটি মূল্য না থাকে" ধারণার সাথে পরিচিত হয়, তবে আমি মনে করি যে কোনও উপযুক্ত প্রোগ্রামার এর কথা শোনা উচিত ছিল, যদিও তিনি মনে করেন এটি একটি ভাল ধারণা বা না। আমি মনে করি একটি পৃথক ফাংশন থাকা আরও একটি "আশ্চর্য" সমস্যা। যদি কোনও প্রোগ্রামার এপিআইয়ের সাথে অপরিচিত থাকে, যখন সে কোনও ডেটা ছাড়াই একটি পরীক্ষা চালায় তিনি দ্রুত আবিষ্কার করতে পারবেন যে কখনও কখনও সে একটি শূন্যতা ফিরে পায়। তবে তিনি কীভাবে অন্য কোনও অস্তিত্ব আবিষ্কার করবেন যদি না ঘটে থাকে যে তার কাছে এমন কোনও ফাংশন থাকতে পারে এবং তিনি ডকুমেন্টেশন পরীক্ষা করেন এবং ডকুমেন্টেশনটি সম্পূর্ণ এবং বোধগম্য হয় না? আমার বরং একটি ফাংশন থাকতে হবে যা আমাকে সর্বদা একটি অর্থপূর্ণ প্রতিক্রিয়া দেয়, বরং দুটি ফাংশন যা আমাকে জানতে এবং উভয়কে কল করতে মনে রাখতে হবে than
যদি কোনও খালি সংগ্রহটি শব্দার্থতভাবে বোঝায় তবে সেটাই আমি ফিরে আসতে পছন্দ করি। GetMessagesInMyInbox()
"আপনার ইনবক্সে সত্যই কোনও বার্তা নেই" যোগাযোগের জন্য একটি খালি সংগ্রহ ফিরিয়ে দেওয়া, অন্যদিকে ফিরে আসা null
তালিকাটি কী দেখতে হবে তা কী বলা উচিত তা বলার জন্য অপর্যাপ্ত তথ্য পাওয়া যায় তা যোগাযোগের ক্ষেত্রে কার্যকর হতে পারে।
null
মান অবশ্যই যুক্তিসঙ্গত বলে মনে হয় না, আমি সেই বিষয়ে আরও সাধারণ পদে ভাবছিলাম। কিছু ভুল হয়ে গেছে এই সত্যটি জানানোর জন্য ব্যতিক্রমগুলিও দুর্দান্ত। আমি বরং এমন দৃশ্যের কথা ভাবছি যেখানে এটি পুরোপুরি সম্ভব এবং পদ্ধতিটি কখনও কখনও কোনও প্রতিক্রিয়া গণনা করতে সক্ষম না হওয়ার জন্য কোনও ত্রুটিই না।
নাল ফিরিয়ে দেওয়া আরও কার্যকর হতে পারে, কারণ কোনও নতুন বস্তু তৈরি হয় না। তবে এটির জন্য প্রায়শই একটি null
চেক (বা ব্যতিক্রম হ্যান্ডলিং require ) প্রয়োজন হবে)
শব্দার্থকভাবে null
এবং একটি খালি তালিকা একই জিনিস বোঝায় না। পার্থক্যগুলি সূক্ষ্ম এবং নির্দিষ্ট পছন্দগুলির মধ্যে একটি পছন্দ অন্যটির চেয়ে ভাল হতে পারে।
আপনার পছন্দ নির্বিশেষে বিভ্রান্তি এড়াতে এটি নথি করুন।
যে কেউ তর্ক করতে পারে যে নাল অবজেক্ট প্যাটার্নের পিছনে যুক্তি খালি সংগ্রহটি ফেরত দেওয়ার পক্ষে একইরকম।
পরিস্থিতির উপর নির্ভর করে. যদি এটি একটি বিশেষ ক্ষেত্রে হয়, তবে নাল ফিরে করুন। যদি ফাংশনটি খালি সংগ্রহটি ফিরিয়ে আনার জন্য ঘটে থাকে তবে স্পষ্টতই এটি ফিরে আসা ঠিক আছে। তবে, অবৈধ প্যারামিটারগুলি বা অন্যান্য কারণে একটি খালি সংগ্রহকে বিশেষ কেস হিসাবে ফিরিয়ে দেওয়া ভাল ধারণা নয়, কারণ এটি একটি বিশেষ কেস শর্তটি মাস্কিং করছে।
আসলে, এক্ষেত্রে আমি সাধারণত এটি ব্যতীত অবহেলিত না হয় তা নিশ্চিত করার জন্য একটি ব্যতিক্রম ছুঁড়তে পছন্দ করি :)
এই বলে যে কোডটি আরও দৃust় করে তোলে (খালি সংগ্রহ ফিরিয়ে দিয়ে) কারণ তাদের নাল অবস্থাটি পরিচালনা করতে হবে না, কারণ এটি কেবল একটি সমস্যাটি মুখোশ করছে যা কলিং কোড দ্বারা পরিচালিত হওয়া উচিত।
আমি তর্ক করব যে null
খালি সংগ্রহের মতো একই জিনিস নয় এবং আপনি যা পছন্দ করছেন তা কোনটি সেরা উপস্থাপন করে তা আপনার চয়ন করা উচিত। বেশিরভাগ ক্ষেত্রে null
কিছুই হয় না (এসকিউএল ব্যতীত)। একটি খালি সংগ্রহ যদিও কিছু খালি কিছু something
আপনার যদি একটি বা অন্যটি চয়ন করতে হয় তবে আমি বলব যে আপনার শূন্যতার চেয়ে খালি সংগ্রহের দিকে ঝুঁকতে হবে। তবে এমন অনেক সময় আসে যখন খালি সংগ্রহটি নাল মান হিসাবে একই জিনিস হয় না।
আপনার ক্লায়েন্টদের পক্ষে সর্বদা চিন্তা করুন (যা আপনার এপিআই ব্যবহার করছে):
'নাল' ফিরিয়ে দেওয়া ক্লায়েন্টদের নাল চেকগুলি সঠিকভাবে পরিচালনা না করার সমস্যাগুলি প্রায়শই সমস্যা তৈরি করে, যা রানটাইমের সময় নালপয়েন্টার এক্সসেপশন তৈরি করে causes আমি এমন কেসগুলি দেখেছি যেখানে এইরকম অনুপস্থিত নাল-চেক একটি অগ্রাধিকারের উত্পাদন সমস্যা (একটি ক্লায়েন্ট নাল মান হিসাবে foreach (...) ব্যবহৃত) বাধ্য করে। পরীক্ষার সময় সমস্যা দেখা দেয় নি, কারণ চালিত ডেটা কিছুটা আলাদা ছিল।
আমি এখানে উপযুক্ত উদাহরণ সহ ব্যাখ্যা দিতে চাই।
এখানে একটি মামলা বিবেচনা করুন ..
int totalValue = MySession.ListCustomerAccounts()
.FindAll(ac => ac.AccountHead.AccountHeadID
== accountHead.AccountHeadID)
.Sum(account => account.AccountValue);
এখানে আমি যে ফাংশনগুলি ব্যবহার করছি তা বিবেচনা করুন ...
1. ListCustomerAccounts() // User Defined
2. FindAll() // Pre-defined Library Function
আমি সহজেই ListCustomerAccount
এবং এর FindAll
পরিবর্তে ব্যবহার করতে পারি ,
int totalValue = 0;
List<CustomerAccounts> custAccounts = ListCustomerAccounts();
if(custAccounts !=null ){
List<CustomerAccounts> custAccountsFiltered =
custAccounts.FindAll(ac => ac.AccountHead.AccountHeadID
== accountHead.AccountHeadID );
if(custAccountsFiltered != null)
totalValue = custAccountsFiltered.Sum(account =>
account.AccountValue).ToString();
}
দ্রষ্টব্য: যেহেতু অ্যাকাউন্টভ্যালু নয় null
, যোগফল () ফাংশনটি ফিরে আসবে না Hence null
সুতরাং আমি এটি সরাসরি ব্যবহার করতে পারি।
খালি সংগ্রহ ফিরিয়ে দেওয়া বেশিরভাগ ক্ষেত্রেই ভাল।
এর কারণ হ'ল কলার বাস্তবায়ন, ধারাবাহিক চুক্তি এবং সহজ বাস্তবায়ন।
যদি কোনও পদ্ধতি খালি ফলাফল নির্দেশ করতে নালার দিকে ফিরে আসে, কলকারীকে অবশ্যই গণনার পাশাপাশি একটি নাল চেকিং অ্যাডাপ্টার প্রয়োগ করতে হবে। এই কোডটি বিভিন্ন কলারে ডুপ্লিকেট করা হয়, সুতরাং কেন এই অ্যাডাপ্টারটি পদ্ধতির ভিতরে রাখবেন না যাতে এটি পুনরায় ব্যবহার করা যায়।
আইইনুমারবেবলের জন্য নালটির বৈধ ব্যবহার অনুপস্থিত ফলাফল, বা অপারেশন ব্যর্থতার ইঙ্গিত হতে পারে, তবে এই ক্ষেত্রে অন্যান্য কৌশলগুলি বিবেচনা করা উচিত, যেমন একটি ব্যতিক্রম ছোঁড়া।
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace StackOverflow.EmptyCollectionUsageTests.Tests
{
/// <summary>
/// Demonstrates different approaches for empty collection results.
/// </summary>
class Container
{
/// <summary>
/// Elements list.
/// Not initialized to an empty collection here for the purpose of demonstration of usage along with <see cref="Populate"/> method.
/// </summary>
private List<Element> elements;
/// <summary>
/// Gets elements if any
/// </summary>
/// <returns>Returns elements or empty collection.</returns>
public IEnumerable<Element> GetElements()
{
return elements ?? Enumerable.Empty<Element>();
}
/// <summary>
/// Initializes the container with some results, if any.
/// </summary>
public void Populate()
{
elements = new List<Element>();
}
/// <summary>
/// Gets elements. Throws <see cref="InvalidOperationException"/> if not populated.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>.</returns>
public IEnumerable<Element> GetElementsStrict()
{
if (elements == null)
{
throw new InvalidOperationException("You must call Populate before calling this method.");
}
return elements;
}
/// <summary>
/// Gets elements, empty collection or nothing.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>, with zero or more elements, or null in some cases.</returns>
public IEnumerable<Element> GetElementsInconvenientCareless()
{
return elements;
}
/// <summary>
/// Gets elements or nothing.
/// </summary>
/// <returns>Returns <see cref="IEnumerable{T}"/> of <see cref="Element"/>, with elements, or null in case of empty collection.</returns>
/// <remarks>We are lucky that elements is a List, otherwise enumeration would be needed.</remarks>
public IEnumerable<Element> GetElementsInconvenientCarefull()
{
if (elements == null || elements.Count == 0)
{
return null;
}
return elements;
}
}
class Element
{
}
/// <summary>
/// http://stackoverflow.com/questions/1969993/is-it-better-to-return-null-or-empty-collection/
/// </summary>
class EmptyCollectionTests
{
private Container container;
[SetUp]
public void SetUp()
{
container = new Container();
}
/// <summary>
/// Forgiving contract - caller does not have to implement null check in addition to enumeration.
/// </summary>
[Test]
public void UseGetElements()
{
Assert.AreEqual(0, container.GetElements().Count());
}
/// <summary>
/// Forget to <see cref="Container.Populate"/> and use strict method.
/// </summary>
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void WrongUseOfStrictContract()
{
container.GetElementsStrict().Count();
}
/// <summary>
/// Call <see cref="Container.Populate"/> and use strict method.
/// </summary>
[Test]
public void CorrectUsaOfStrictContract()
{
container.Populate();
Assert.AreEqual(0, container.GetElementsStrict().Count());
}
/// <summary>
/// Inconvenient contract - needs a local variable.
/// </summary>
[Test]
public void CarefulUseOfCarelessMethod()
{
var elements = container.GetElementsInconvenientCareless();
Assert.AreEqual(0, elements == null ? 0 : elements.Count());
}
/// <summary>
/// Inconvenient contract - duplicate call in order to use in context of an single expression.
/// </summary>
[Test]
public void LameCarefulUseOfCarelessMethod()
{
Assert.AreEqual(0, container.GetElementsInconvenientCareless() == null ? 0 : container.GetElementsInconvenientCareless().Count());
}
[Test]
public void LuckyCarelessUseOfCarelessMethod()
{
// INIT
var praySomeoneCalledPopulateBefore = (Action)(()=>container.Populate());
praySomeoneCalledPopulateBefore();
// ACT //ASSERT
Assert.AreEqual(0, container.GetElementsInconvenientCareless().Count());
}
/// <summary>
/// Excercise <see cref="ArgumentNullException"/> because of null passed to <see cref="Enumerable.Count{TSource}(System.Collections.Generic.IEnumerable{TSource})"/>
/// </summary>
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void UnfortunateCarelessUseOfCarelessMethod()
{
Assert.AreEqual(0, container.GetElementsInconvenientCareless().Count());
}
/// <summary>
/// Demonstrates the client code flow relying on returning null for empty collection.
/// Exception is due to <see cref="Enumerable.First{TSource}(System.Collections.Generic.IEnumerable{TSource})"/> on an empty collection.
/// </summary>
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void UnfortunateEducatedUseOfCarelessMethod()
{
container.Populate();
var elements = container.GetElementsInconvenientCareless();
if (elements == null)
{
Assert.Inconclusive();
}
Assert.IsNotNull(elements.First());
}
/// <summary>
/// Demonstrates the client code is bloated a bit, to compensate for implementation 'cleverness'.
/// We can throw away the nullness result, because we don't know if the operation succeeded or not anyway.
/// We are unfortunate to create a new instance of an empty collection.
/// We might have already had one inside the implementation,
/// but it have been discarded then in an effort to return null for empty collection.
/// </summary>
[Test]
public void EducatedUseOfCarefullMethod()
{
Assert.AreEqual(0, (container.GetElementsInconvenientCarefull() ?? Enumerable.Empty<Element>()).Count());
}
}
}
আমি এটিকে আমার বিলিয়ন-ডলারের ভুল বলছি ... তখন আমি কোনও বস্তু-ভিত্তিক ভাষায় রেফারেন্সের জন্য প্রথম বিস্তৃত টাইপ সিস্টেমটি ডিজাইন করছিলাম। আমার লক্ষ্যটি নিশ্চিত করা ছিল যে সমস্ত উল্লেখের ব্যবহার সম্পূর্ণরূপে নিরাপদ হওয়া উচিত, সংকলক দ্বারা স্বয়ংক্রিয়ভাবে চেক করা উচিত। তবে নাল রেফারেন্স দেওয়ার প্রলোভনটি আমি প্রতিহত করতে পারিনি, কেবল কারণ এটি কার্যকর করা এত সহজ ছিল। এর ফলে অসংখ্য ত্রুটি, দুর্বলতা এবং সিস্টেম ক্র্যাশ হয়েছে, যা সম্ভবত চল্লিশ বছরে এক বিলিয়ন ডলার ব্যথা এবং ক্ষতির কারণ হয়ে দাঁড়িয়েছে। - টনি হোয়ার, ALGOL ডাব্লু এর উদ্ভাবক।
সাধারণভাবে বিস্তৃত বিষ্ঠা ঝড়ের জন্য এখানে দেখুন null
। আমি undefined
অন্য যে বিবৃতিটি দিয়ে একমত নই null
, তবে এটি এখনও পড়ার মতো। এবং এটি ব্যাখ্যা করে, কেন আপনার null
জিজ্ঞাসা করা মামলায় নয় কেবল আপনার কেন এড়ানো উচিত । সারমর্মটি, তাnull
কোনও ভাষায় একটি বিশেষ ক্ষেত্রে। আপনাকে null
ব্যতিক্রম হিসাবে ভাবতে হবে । undefined
সেইভাবে আলাদা, সেই কোডটি অপরিজ্ঞিত আচরণের সাথে ডিল করা বেশিরভাগ ক্ষেত্রে কেবল একটি বাগ। সি এবং অন্যান্য বেশিরভাগ ভাষারও অপরিবর্তিত আচরণ রয়েছে তবে বেশিরভাগেরই ভাষায় এর জন্য সনাক্তকারী নেই।
জটিলতা পরিচালনার দৃষ্টিকোণ থেকে, একটি প্রাথমিক সফ্টওয়্যার ইঞ্জিনিয়ারিং উদ্দেশ্য, আমরা অপ্রয়োজনীয় প্রচার এড়াতে চাই কোনও এপিআই-র ক্লায়েন্টগুলিতে সাইক্লোমেটিক জটিলতার । ক্লায়েন্টের কাছে একটি নাল ফিরিয়ে দেওয়া তাদের অন্য কোড শাখার সাইক্লোমেটিক জটিলতার ব্যয় ফিরিয়ে দেওয়ার মতো।
(এটি ইউনিট পরীক্ষার বোঝার সাথে সামঞ্জস্য করে You খালি সংগ্রহের রিটার্ন কেস ছাড়াও আপনাকে নাল রিটার্নের ক্ষেত্রে একটি পরীক্ষা লিখতে হবে))