C#তে কেন এমন একটি রেফারেন্স টাইপ স্ট্রিং করা হয় যা মান টাইপের মত আচরণ করে?




string clr (10)

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

কেন স্ট্রিং ঠিক একটি মান টাইপ তারপর হয় না?


এটি একটি পুরানো প্রশ্নটির একটি উত্তরের উত্তর, তবে অন্যান্য সমস্ত উত্তরগুলি পয়েন্টটি অনুপস্থিত, যা 2005 সালে .NET 2.0 পর্যন্ত জেনেটিক ছিল না।

String একটি মান টাইপের পরিবর্তে একটি রেফারেন্স টাইপ কারণ এটি Microsoft- এর জন্য অপরিহার্য গুরুত্বের কারণ ছিল যে স্ট্রিংগুলি System.Collection.ArrayList - System.Collection.ArrayList হিসাবে অ-জেনারিক সংগ্রহগুলির সবচেয়ে কার্যকরী উপায়ে সঞ্চয় করা যেতে পারে

একটি অ-জেনেরিক সংগ্রহে একটি মান-টাইপ সংরক্ষণ করার জন্য বক্সিং নামক টাইপ object বিশেষ রূপান্তর প্রয়োজন। যখন CLR বাক্সগুলি একটি মান টাইপ করে, তখন এটি একটি System.Object ভিতরে মানটি System.Object দেয়। পরিচালনা করে এবং এটি পরিচালিত System.Object সংরক্ষণ করে।

সংগ্রহ থেকে মানটি পড়ার জন্য অপব্যবহার বলা হয় এমন বিপরীত ক্রিয়াকলাপ প্রয়োজন।

বক্সিং এবং আনবক্সিং উভয়ই অ-নগদ খরচ: বক্সিং একটি অতিরিক্ত বরাদ্দ প্রয়োজন, unboxing টাইপ চেকিং প্রয়োজন।

কিছু উত্তর ভুলভাবে দাবি করে যে string মান টাইপ হিসাবে প্রয়োগ করা হতে পারে না কারণ এটির আকার পরিবর্তনশীল। প্রকৃতপক্ষে স্ট্রিংটি একটি ছোট স্ট্রিং অপ্টিমাইজেশান কৌশল ব্যবহার করে স্থির-দৈর্ঘ্যের ডেটা গঠন হিসাবে বাস্তবায়ন করা সহজ: স্ট্রিংগুলিকে ইউনিকোড অক্ষরের ক্রম হিসাবে সরাসরি সংরক্ষণ করা হবে যা বড় স্ট্রিংগুলিকে বাদে বহিরাগত বাফারের জন্য পয়েন্টার হিসাবে সংরক্ষণ করা হবে। উভয় উপস্থাপনা একই নির্দিষ্ট দৈর্ঘ্য, অর্থাৎ একটি পয়েন্টার আকার আছে ডিজাইন করা যেতে পারে।

জেনেরিক্স যদি প্রথম দিন থেকে অস্তিত্বমান থাকে তবে আমি অনুমান করি যে মানের মান হিসাবে স্ট্রিং থাকা সম্ভবত সরল সেমেটিকস, আরও ভাল মেমরি ব্যবহার এবং উন্নত ক্যাশে স্থানীয়তার সাথে একটি ভাল সমাধান ছিল। একটি List<string> শুধুমাত্র ছোট স্ট্রিং ধারণকারী মেমরি একটি একক সংলগ্ন ব্লক হতে পারে।


রেফারেন্স প্রকার এবং মান প্রকারের মধ্যে পার্থক্যটি মূলত ভাষাটির নকশাতে একটি কার্য সম্পাদন বাণিজ্য। রেফারেন্স প্রকার নির্মাণ এবং ধ্বংস এবং আবর্জনা সংগ্রহের উপর কিছু overhead আছে, কারণ তারা হিপ উপর নির্মিত হয়। অন্যদিকে মানগুলির ধরনগুলি পদ্ধতি কলগুলির উপরে ওভারহেড থাকে (যদি তথ্য আকার একটি পয়েন্টারের চেয়ে বড় হয়), কারণ সমগ্র বস্তু কেবল একটি পয়েন্টারের চেয়ে অনুলিপি করা হয়। কারণ পংক্তির আকারের চেয়ে স্ট্রিংগুলি (এবং সাধারণতঃ) অনেক বড় হতে পারে, সেগুলি রেফারেন্স প্রকার হিসাবে ডিজাইন করা হয়। এছাড়াও, Servy নির্দেশ করে, একটি মান টাইপ আকার আকার কম্পাইল সময় জানা আবশ্যক, যা সবসময় স্ট্রিং ক্ষেত্রে হয় না।

পরিবর্তনযোগ্যতা প্রশ্ন একটি পৃথক সমস্যা। উভয় রেফারেন্স ধরনের এবং মান ধরনের পরিবর্তনযোগ্য বা অপরিবর্তনীয় হতে পারে। মূল্যের ধরনগুলি সাধারণত অনাক্রম্য, যদিও পরিবর্তনযোগ্য মান প্রকারের শব্দার্থগুলি বিভ্রান্তিকর হতে পারে।

রেফারেন্স ধরন সাধারণত পরিবর্তনযোগ্য, কিন্তু এটি ইন্দ্রিয়গ্রাহ্য হিসাবে অনাক্রম্য হিসাবে ডিজাইন করা যেতে পারে। এটি কিছু নির্দিষ্ট অপ্টিমাইজেশান সম্ভব কারণ স্ট্রিং অপরিবর্তনীয় হিসাবে সংজ্ঞায়িত করা হয়। উদাহরণস্বরূপ, যদি একই স্ট্রিংটি একই প্রোগ্রামে একাধিক বার ঘটে থাকে (যা বেশ সাধারণ), কম্পাইলার একই বস্তুর পুনঃব্যবহার করতে পারে।

তাই কেন "==" লেখা দ্বারা স্ট্রিং তুলনায় overloaded হয়? এটি সবচেয়ে দরকারী শব্দকোষ কারণ। যদি দুটি স্ট্রিং পাঠ্য সমান হয়, তবে এটি অপটিমাইজেশনগুলির কারণে একই বস্তুর রেফারেন্স হতে পারে বা নাও হতে পারে। সুতরাং রেফারেন্স তুলনা বেশ অর্থহীন, টেক্সট তুলনা প্রায় সবসময় আপনি চান।

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


শুধুমাত্র স্ট্রিং অপরিবর্তনীয় রেফারেন্স ধরনের হয়। মাল্টি-কাস্ট প্রতিনিধিও। এটা লিখতে নিরাপদ কেন?

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

আমি মনে করি যে স্ট্রিং অপরিবর্তনীয় কারণ এটি তাদের সাথে কাজ করার এবং মেমরি বরাদ্দ করার সবচেয়ে নিরাপদ পদ্ধতি। কেন তারা মূল্য ধরনের হয় না? পূর্ববর্তী লেখক স্ট্যাক আকার ইত্যাদি সম্পর্কে সঠিক। আমি স্ট্রিংগুলিকে একটি রেফারেন্সের ধরনগুলিকে প্রোগ্রামে একই ধ্রুবক স্ট্রিং ব্যবহার করার সময় সমাবেশ আকারে সংরক্ষণ করার অনুমতি দেব। আপনি যদি সংজ্ঞায়িত

string s1 = "my string";
//some code here
string s2 = "my string";

সম্ভাবনা হল "আমার স্ট্রিং" ধ্রুবক উভয় দৃষ্টান্ত আপনার সমাবেশে শুধুমাত্র একবার বরাদ্দ করা হবে।

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

যদি আপনি একটি লাইব্রেরি তৈরি করতে চান, যেখানে আপনি আপনার ফাংশনে একটি বিশাল স্ট্রিং পাস করতে চান, তবে স্ট্রিংবিল্ডার হিসাবে স্ট্রিম বা একটি স্ট্রিম হিসাবে একটি প্যারামিটার সংজ্ঞায়িত করুন।


তারা বিশাল হতে পারে, কারণ স্ট্রিং মান ধরনের হয় না, এবং হিপ সংরক্ষণ করা প্রয়োজন। মূল্যের ধরনগুলি (এখনও পর্যন্ত CLR এর সমস্ত বাস্তবায়নে) স্ট্যাকে সংরক্ষিত। স্টক বরাদ্দকরণ স্ট্রিং সকল ধরণের জিনিস ভাঙবে: স্ট্যাকটি 32-বিটের জন্য মাত্র 1 এমবি এবং 64-বিটের জন্য 4 এমবি, আপনাকে প্রতিটি স্ট্রিং বাক্সে থাকতে হবে, একটি অনুলিপি শাস্তি বহন করতে হবে, আপনি স্ট্রিংগুলি intern এবং মেমরির ব্যবহার করতে পারবেন না বেলুন, ইত্যাদি ...

(সম্পাদনা: মান টাইপ স্টোরেজটি একটি বাস্তবায়ন বিশদ হিসাবে যোগ করা স্প্লিফিকেশন, যা এই অবস্থার দিকে পরিচালিত করে যেখানে আমাদের কাছে মান সিমেটিক্সের একটি টাইপ আছে যা System.ValueType থেকে উত্তরাধিকারসূত্রে প্রাপ্ত নয়। ধন্যবাদ বেন।)


প্রকৃতপক্ষে স্ট্রিং মান ধরনের খুব সামঞ্জস্য আছে। প্রারম্ভিকদের জন্য, সমস্ত মূল্যের ধরন অপরিবর্তনীয় নয়, আপনি চান এমন একটি ইন্টারপোজের মান পরিবর্তন করতে পারেন এবং এটি এখনও স্ট্যাকের একই ঠিকানা হবে।

স্ট্রিংগুলি খুব ভাল কারণে অপরিবর্তনীয়, এটি একটি রেফারেন্স টাইপের সাথে কিছু করার নেই, তবে মেমরি পরিচালনার সাথে অনেক কিছু করার আছে। স্ট্রিং সাইজ পরিচালিত হিপের চারপাশে জিনিসগুলি সরানোর চেয়ে এটি একটি নতুন বস্তু তৈরি করার জন্য আরও কার্যকর। আমি মনে করি আপনি একসঙ্গে মান / রেফারেন্স ধরন এবং অপরিবর্তনীয় বস্তু ধারণা মিশ্রিত করছি।

যতদূর "==": আপনি যেমন বলেছেন "==" একটি অপারেটর ওভারলোড, এবং আবার এটি স্ট্রিংগুলির সাথে কাজ করার সময় ফ্রেমওয়ার্ককে আরও কার্যকর করার জন্য একটি খুব ভাল কারণের জন্য প্রয়োগ করা হয়েছিল।


আপনি কিভাবে string একটি রেফারেন্স টাইপ বলতে পারেন? আমি এটা বাস্তবায়িত কিভাবে গুরুত্বপূর্ণ তা নিশ্চিত নই। C # এ স্ট্রিংগুলি অবিকল অপরিবর্তনীয় তাই আপনাকে এই সমস্যাটির বিষয়ে চিন্তা করতে হবে না।


এটি একটি মান টাইপ নয় কারণ কার্যকরী (স্থান এবং সময়!) ভয়ানক হবে যদি এটি একটি মান টাইপ এবং তার মানটি প্রতিবার পাস করা হয় এবং পদ্ধতি থেকে ফেরত পাঠানো হয়।

এটি বিশ্বব্যাপী বজায় রাখা মূল্য semantics আছে। আপনি কল্পনা করতে পারেন যদি এটি কোড কত কঠিন হবে

string s = "hello";
string t = "hello";
bool b = (s == t);

false সেট করা b ? কোন অ্যাপ্লিকেশন সম্পর্কে ঠিক কোডিং কঠিন হবে কল্পনা করুন।


স্ট্রিং অক্ষর অ্যারে গঠিত হয় ঠিক যেমন সহজ নয়। আমি চরিত্র অ্যারে হিসাবে স্ট্রিং তাকান []। অতএব তারা গাদা হয় কারণ রেফারেন্স মেমরি অবস্থান স্ট্যাকে সংরক্ষিত হয় এবং হিপের অ্যারের মেমরি অবস্থানের শুরুতে নির্দেশ করে। স্ট্রিং আকার এটি বরাদ্দ আগে পরিচিত হয় না ... হিপ জন্য নিখুঁত।

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


একটি খুব সহজ শব্দের মধ্যে যে কোনও মানকে নির্দিষ্ট আকারের মান হিসাবে বিবেচনা করা যেতে পারে।


এটি প্রধানত একটি কর্মক্ষমতা সমস্যা।

স্ট্রিং আচরণের মতো কোড টাইপ করার সময় মান টাইপটি সাহায্য করে, তবে এটি একটি মান টাইপ থাকা একটি বিশাল কর্মক্ষমতা আঘাত করবে।

গভীরতার জন্য, নেট কাঠামোতে স্ট্রিংগুলিতে একটি চমৎকার নিবন্ধে একটি উঁকি নিন।





reference-type