আমি তাদের দেখা করেছি উভয় C # এর কোডের অসংখ্য টুকরা ব্যবহৃত হচ্ছে, এবং আমি যখন ব্যবহার করতে জানতে চাই i++বা ++i( iমত একটি সংখ্যা পরিবর্তনশীল হচ্ছে int, float, double, ইত্যাদি)। কে এই জানেন?
আমি তাদের দেখা করেছি উভয় C # এর কোডের অসংখ্য টুকরা ব্যবহৃত হচ্ছে, এবং আমি যখন ব্যবহার করতে জানতে চাই i++বা ++i( iমত একটি সংখ্যা পরিবর্তনশীল হচ্ছে int, float, double, ইত্যাদি)। কে এই জানেন?
উত্তর:
অদ্ভুতভাবে দেখে মনে হচ্ছে অন্য দুটি উত্তর এটির বানান করে না, এবং এটি অবশ্যই বলা বাহুল্য:
i++মানে 'আমাকে তার মান বলুন i, তারপরে বৃদ্ধি'
++iমানে 'ইনক্রিমেন্ট i, তারপরে আমাকে মান বলুন'
তারা হ'ল প্রাক-ইনক্রিমেন্ট, পোস্ট-ইনক্রিমেন্ট অপারেটর। উভয় ক্ষেত্রে চলকটি বর্ধিত হয় , তবে আপনি যদি একই ক্ষেত্রে উভয় এক্সপ্রেশনটির মান গ্রহণ করেন তবে ফলাফলটি পৃথক হবে।
দুর্ভাগ্যক্রমে এখানে ইতিমধ্যে পোস্ট করা এই প্রশ্নের সাধারণ উত্তরটি হ'ল, একটি "অবশিষ্ট ক্রিয়াকলাপের" আগে "ইনক্রিমেন্ট" করে এবং অন্যটি "অপারেশনটি" পরে "অপারেশনগুলি" রাখে। যদিও স্বজ্ঞাতভাবে ধারণাটি জুড়ে পেয়েছে, তবুও উক্তিটি সম্পূর্ণরূপে ভুল । সময় ঘটনা ক্রম অত্যন্ত C # এর ভাল-সংজ্ঞায়িত, এবং এটা প্রবলভাবে হয় না ক্ষেত্রে যে ++, উপসর্গ (++, Var) এবং পোস্টসাফিক্স (Var ++,) সংস্করণ অন্যান্য অপারেশন থেকে সম্মান সঙ্গে একটি ভিন্ন অনুক্রমে কিছু করার।
আপনি এই প্রশ্নের অনেক ভুল উত্তর দেখতে পাবেন এটি আশ্চর্যজনক নয়। একটি দুর্দান্ত অনেকে "নিজেকে সি # শেখায়" বইগুলি এটিকে ভুলও বলে ফেলে। এছাড়াও, সি # এটি করার পদ্ধতিটি সি কিভাবে এটি করে তার চেয়ে আলাদা। অনেক লোক সি # এবং সি একই ভাষা বলে মনে করেন; তারা না. আমার মতে সি # তে ইনক্রিমেন্ট এবং হ্রাস অপারেটরগুলির ডিজাইন সিতে এই অপারেটরগুলির ডিজাইনের ত্রুটিগুলি এড়িয়ে চলে
উপ # এবং উপসর্গ ++ এর সঠিক ক্রিয়াকলাপ সি # তে কি তা নির্ধারণ করতে দুটি প্রশ্নের উত্তর দিতে হবে। প্রথম প্রশ্নটি ফলাফল কী? এবং দ্বিতীয় প্রশ্নটি কখন বর্ধনের পার্শ্ব প্রতিক্রিয়া হয়?
উভয় প্রশ্নের উত্তর কী তা স্পষ্ট নয়, তবে আপনি এটি একবার দেখলেই এটি আসলে বেশ সহজ। ভ্যারিয়েবল এক্স এর জন্য x ++ এবং ++ x কী করবে তা আমি আপনার জন্য স্পষ্টভাবে বানান করি।
উপসর্গ ফর্মের জন্য (++ এক্স):
পোস্টফিক্স ফর্মের জন্য (x ++):
কিছু বিষয় লক্ষ্য করুন:
প্রথমত, সময় ঘটনা ক্রম ঠিক উভয় ক্ষেত্রেই একই । আবার, একেবারে এমনটি নয় যে সময়ের সাথে সাথে ইভেন্টগুলির ক্রম উপসর্গ এবং পোস্টফিক্সের মধ্যে পরিবর্তিত হয়। এটি মূল্যায়নের অন্যান্য মূল্যায়নের আগে বা অন্যান্য মূল্যায়নের পরে ঘটে তা সম্পূর্ণ মিথ্যা। মূল্যায়ন হ'ল উভয় ক্ষেত্রে একই ক্রমে একই হিসাবে আপনি দেখতে পাচ্ছেন যে 1 থেকে 4 ধাপটি অভিন্ন হচ্ছে। শুধুমাত্র পার্থক্য নেই শেষ ধাপে - ফলাফলের অস্থায়ী বা নতুন, বৃদ্ধি মান মান কিনা।
আপনি সহজেই একটি সাধারণ সি # কনসোল অ্যাপ্লিকেশন দিয়ে এটি প্রদর্শিত করতে পারেন:
public class Application
{
public static int currentValue = 0;
public static void Main()
{
Console.WriteLine("Test 1: ++x");
(++currentValue).TestMethod();
Console.WriteLine("\nTest 2: x++");
(currentValue++).TestMethod();
Console.WriteLine("\nTest 3: ++x");
(++currentValue).TestMethod();
Console.ReadKey();
}
}
public static class ExtensionMethods
{
public static void TestMethod(this int passedInValue)
{
Console.WriteLine("Current:{0} Passed-in:{1}",
Application.currentValue,
passedInValue);
}
}
ফলাফলগুলি এখানে ...
Test 1: ++x
Current:1 Passed-in:1
Test 2: x++
Current:2 Passed-in:1
Test 3: ++x
Current:3 Passed-in:3
প্রথম পরীক্ষায়, আপনি দেখতে পাচ্ছেন যে উভয় currentValueএবং যা TestMethod()এক্সটেনশনে পাস হয়েছিল একই প্রত্যাশা অনুযায়ী একই মান দেখায়।
যাইহোক, দ্বিতীয় ক্ষেত্রে, লোকেরা আপনাকে বলার চেষ্টা করবে যে কল করার পরে বর্ধন currentValueঘটে , তবে ফলাফল থেকে আপনি দেখতে পাচ্ছেন , 'কারেন্ট: 2' ফলাফল দ্বারা নির্দেশিত কলটির আগে এটি ঘটে ।TestMethod()
এই ক্ষেত্রে, প্রথমে এর মান currentValueএকটি অস্থায়ীভাবে সংরক্ষণ করা হয়। এরপরে, সেই মানটির বর্ধিত সংস্করণ আবার সংরক্ষণ করা হয় currentValueতবে অস্থায়ী স্পর্শ না করে যা এখনও মূল মানটি সঞ্চয় করে। অবশেষে যে অস্থায়ী পাস করা হয় TestMethod()। কল করার পরে যদি বর্ধিততা ঘটে থাকে TestMethod()তবে এটি একই, অ-বর্ধিত মানটি দু'বার লিখে ফেলবে, তবে তা হয় না।
এটি লক্ষ করা গুরুত্বপূর্ণ যে উভয়
currentValue++এবং++currentValueক্রিয়াকলাপ থেকে প্রত্যাশিত মান অস্থায়ী নয় এবং সেই সময় চলকটিতে সঞ্চিত প্রকৃত মানের উপর ভিত্তি করে হয় অপারেশনটি প্রস্থান হয়।উপরের ক্রিয়াকলাপের পুনরায় স্মরণ করুন, প্রথম দুটি পদক্ষেপ অস্থায়ী মধ্যে ভেরিয়েবলের তত্কালীন বর্তমান মানটি অনুলিপি করে। এটিই রিটার্নের মান গণনা করতে ব্যবহৃত হয়; উপসর্গ সংস্করণের ক্ষেত্রে, প্রত্যয় সংস্করণের ক্ষেত্রে এটি অস্থায়ী মান বাড়িয়ে তোলে, এটি সরাসরি / অ-বর্ধিত মান। অস্থায়ী মধ্যে প্রাথমিক স্টোরেজ পরে পরিবর্তনশীল নিজেই আর পড়া হয় না।
আরও সহজভাবে বলতে গেলে, পোস্টফিক্স সংস্করণটি ভেরিয়েবল থেকে পড়া অর্থটি (যেমন অস্থায়ীটির মান) ফেরত দেয় যখন উপসর্গ সংস্করণটি ভেরিয়েবেলে (যেমন অস্থায়ীটির বর্ধিত মান) ফেরত দেওয়া মানটি ফিরিয়ে দেয়। ভেরিয়েবলের মানও ফেরত দেবে না।
এটি বুঝতে গুরুত্বপূর্ণ কারণ ভেরিয়েবলটি নিজেই অস্থির হতে পারে এবং অন্য থ্রেডে পরিবর্তিত হয়েছিল যার অর্থ সেই ক্রিয়াকলাপগুলির রিটার্নের মান চলকটিতে সঞ্চিত বর্তমান মান থেকে পৃথক হতে পারে।
লোকেরা অগ্রাধিকার, সাহচর্যতা সম্পর্কে খুব বিভ্রান্ত হওয়ার পক্ষে আশ্চর্যজনকভাবে সাধারণ, এবং যে দিক থেকে পার্শ্ব প্রতিক্রিয়াগুলি কার্যকর করা হয়, আমি সন্দেহ করি বেশিরভাগ কারণ এটি সি এর মধ্যে এত বিভ্রান্তিকর তাই সি # এই সমস্ত ক্ষেত্রে কম বিভ্রান্ত হওয়ার জন্য সাবধানে ডিজাইন করা হয়েছে। এই বিষয়গুলির কিছু অতিরিক্ত বিশ্লেষণের জন্য, আমাকে আরও অন্তর্ভুক্ত করে এই ধারণাটির মিথ্যাচারটি প্রদর্শন করে যে উপসর্গ এবং পোস্টফিক্স অপারেশনগুলি "সময়ে সময়ে জিনিস সরিয়ে নিয়ে যায়" দেখুন:
https://ericlippert.com/2009/08/10/precedence-vs-order-redux/
যা এই এই প্রশ্নে নেতৃত্ব দিয়েছে:
int [] আরার = {0}; int মান = আরআর [আরআর [0] ++]; মান = 1?
আপনি এই বিষয়ে আমার আগের নিবন্ধগুলিতেও আগ্রহী হতে পারেন:
https://ericlippert.com/2008/05/23/precedence-vs-associativity-vs-order/
এবং
https://ericlippert.com/2007/08/14/c-and-the-pit-of-despair/
এবং একটি আকর্ষণীয় ক্ষেত্রে যেখানে সি সঠিকতা সম্পর্কে যুক্তিযুক্ত করে তোলে:
https://docs.microsoft.com/archive/blogs/ericlippert/bad-recursion-revisited
এছাড়াও, অন্যান্য ক্রিয়াকলাপগুলির যেমন পার্শ্ব প্রতিক্রিয়াযুক্ত, যেমন জড়িত সরল কার্যভারগুলি বিবেচনা করার সময় আমরা অনুরূপ সূক্ষ্ম সমস্যাগুলিতে চলে যাই:
https://docs.microsoft.com/archive/blogs/ericlippert/chaining-simple-assignments-is-not-so-simple
এবং কেন বর্ধিত অপারেটরগুলি ভেরিয়েবলের পরিবর্তে সি # তে মানগুলিতে ফল দেয় সে সম্পর্কে একটি আকর্ষণীয় পোস্ট এখানে রয়েছে :
i++বা ++iকোডে ব্যবহৃত হয়, ব্যাকগ্রাউন্ডে চলছে এমন জিনিসগুলি; পটভূমিতে । এই স্তরে কী চলছে তার উপরে বিমূর্ত স্তরে আরোহণের জন্য আমি সি # লিখি, সুতরাং যদি এটি আপনার সি # কোডের পক্ষে সত্যিই গুরুত্বপূর্ণ হয় তবে আপনি ইতিমধ্যে ভুল ভাষায় থাকতে পারেন।
i++;) for (int i = 0; i < x; i++)... এবং আমি খুব খুব এর জন্য খুশি! (এবং আমি কখনও উপসর্গ অপারেটর ব্যবহার করি না)। যদি আমাকে এমন কিছু লিখতে হয় যা ডিসিফার করার জন্য সিনিয়র প্রোগ্রামারকে 2 মিনিটের প্রয়োজন হয় ... আচ্ছা ... কোডের আরও একটি লাইন লিখতে বা একটি অস্থায়ী ভেরিয়েবলের পরিচয় করিয়ে দেওয়া ভাল :-) আমি মনে করি আপনার "নিবন্ধ" (আমি জিতেছি) এটিকে "উত্তর" বলবেন না) আমার পছন্দটিকে সত্য বলে প্রমাণিত করে :-)
যদি তোমার থাকে:
int i = 10;
int x = ++i;
তাহলে xহবে 11।
তবে আপনার যদি:
int i = 10;
int x = i++;
তাহলে xহবে 10।
এরিক উল্লেখ করেছেন যে নোট হিসাবে, উভয় ক্ষেত্রে একই সময়ে বর্ধন ঘটে, তবে ফলাফলের ফলে পৃথক হওয়া মানটি কী আলাদা হয় (ধন্যবাদ এরিক!)
সাধারণত, আমি না ব্যবহার করতে চাই ++iযদি ভাল কারণ না থাকে। উদাহরণস্বরূপ, একটি লুপ লেখার সময়, আমি ব্যবহার করতে পছন্দ করি:
for (int i = 0; i < 10; ++i) {
}
অথবা, যদি আমাকে কেবল একটি পরিবর্তনশীল বৃদ্ধি করতে হয় তবে আমি এটি ব্যবহার করতে চাই:
++x;
সাধারণত, একটি উপায়ে বা অন্যটির তেমন তাত্পর্য থাকে না এবং কোডিং শৈলীতে নেমে আসে তবে আপনি যদি অন্য কার্যাদিগুলির মধ্যে অপারেটরগুলি ব্যবহার করে থাকেন (যেমন আমার মূল উদাহরণগুলির মতো) তবে সম্ভাব্য পার্শ্ব প্রতিক্রিয়া সম্পর্কে সচেতন হওয়া গুরুত্বপূর্ণ।
iপরিবর্তে পরিবর্তনশীল নামের জন্য ব্যবহার করতে সম্পাদনা করেছি var।
int i = 0;
Console.WriteLine(i++); // Prints 0. Then value of "i" becomes 1.
Console.WriteLine(--i); // Value of "i" becomes 0. Then prints 0.
এটা কি তোমার প্রশ্নের উত্তর ?
অপারেটর যেভাবে কাজ করে তা হ'ল এটি একই সাথে বর্ধিত হয়, তবে এটি যদি চলকের আগে হয় তবে অভিব্যক্তিটি বর্ধিত / হ্রাসযুক্ত ভেরিয়েবলের সাথে মূল্যায়ন করবে:
int x = 0; //x is 0
int y = ++x; //x is 1 and y is 1
এটি যদি ভেরিয়েবলের পরে হয় তবে বর্তমান বিবৃতিটি মূল ভেরিয়েবলের সাথে কার্যকর হবে, যেন এটি এখনও বাড়ানো / হ্রাসপ্রাপ্ত হয়নি:
int x = 0; //x is 0
int y = x++; //'y = x' is evaluated with x=0, but x is still incremented. So, x is 1, but y is 0
প্রয়োজনীয়তা না থাকলে আমি প্রি-ইনক্রিমেন্ট / হ্রাস (++ এক্স) ব্যবহারে ডিসিপির সাথে সম্মত। সত্যিই কেবলমাত্র আমি যখন পোস্ট-ইনক্রিমেন্ট / হ্রাস ব্যবহার করি তখন সেই ধরণের লুপ বা লুপ হয়। এই লুপগুলি একই:
while (x < 5) //evaluates conditional statement
{
//some code
++x; //increments x
}
অথবা
while (x++ < 5) //evaluates conditional statement with x value before increment, and x is incremented
{
//some code
}
অ্যারেগুলি এবং অন্যান্য যেমন সূচীকরণ করার সময় আপনি এটিও করতে পারেন:
int i = 0;
int[] MyArray = new int[2];
MyArray[i++] = 1234; //sets array at index 0 to '1234' and i is incremented
MyArray[i] = 5678; //sets array at index 1 to '5678'
int temp = MyArray[--i]; //temp is 1234 (becasue of pre-decrement);
ইত্যাদি ইত্যাদি ...
কেবল রেকর্ডের জন্য, সি ++ এ আপনি যদি ব্যবহার করতে পারেন তবে (যেমন) আপনি ক্রিয়াকলাপের ক্রমটি বিবেচনা করেন না (আপনি কেবল বৃদ্ধি বা হ্রাস করতে চান এবং পরে এটি ব্যবহার করতে চান) উপসর্গ অপারেটর আরও দক্ষ কারণ এটি না করে অবজেক্টের একটি অস্থায়ী অনুলিপি তৈরি করতে হবে। দুর্ভাগ্যক্রমে, বেশিরভাগ লোকেরা উপসর্গ (++ var) এর পরিবর্তে পসফিক্স (var ++) ব্যবহার করে, কারণ এটি প্রাথমিকভাবে আমরা শিখেছি। (আমাকে একটি সাক্ষাত্কারে এ সম্পর্কে জিজ্ঞাসা করা হয়েছিল)। এটি সি # তে সত্য কিনা তা নিশ্চিত নয়, তবে আমি ধরে নিই যে এটি হবে।