কেন সমবায়তা এবং বৈপরীত্য মূল্য প্রকারকে সমর্থন করে না


149

IEnumerable<T>হয় সহ-বৈকল্পিক কিন্তু এটা মান টাইপ, শুধু শুধুমাত্র রেফারেন্সের টাইপ সমর্থন করে না। নীচের সহজ কোডটি সফলভাবে সংকলিত হয়েছে:

IEnumerable<string> strList = new List<string>();
IEnumerable<object> objList = strList;

কিন্তু থেকে পরিবর্তন stringকরতে intকম্পাইল ভুল পান করবে:

IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList;

কারণটি এমএসডিএন-তে ব্যাখ্যা করা হয়েছে :

বৈকল্পিকতা কেবলমাত্র রেফারেন্স ধরণের ক্ষেত্রে প্রযোজ্য; যদি আপনি কোনও ভেরিয়েন্ট টাইপ প্যারামিটারের জন্য কোনও মান প্রকার নির্দিষ্ট করে থাকেন, তবে সেই ধরণের পরামিতি ফলাফল নির্মিত ধরণের জন্য অদক্ষ।

আমি অনুসন্ধান করে দেখেছি যে কয়েকটি প্রশ্নের কারণ হিসাবে উল্লেখ করা হয়েছে তা হ'ল মূল্য এবং রেফারেন্স ধরণের মধ্যে বক্সিং । তবে এটি এখনও আমার মন পরিষ্কার করে না যে বক্সিংয়ের কারণটি কেন?

কেউ দয়া করে একটি সহজ এবং বিস্তারিত ব্যাখ্যা দিতে পারেন কেন কেন সমানতা এবং বৈপরীত্য মূল্য প্রকারকে সমর্থন করে না এবং বক্সিং কীভাবে এটিকে প্রভাবিত করে?


3
: আমার অনুরূপ প্রশ্নের এরিকের উত্তর দেখার stackoverflow.com/questions/4096299/...
কাঁটা

উত্তর:


126

মূলত, সিএলআর নিশ্চিত করতে পারে যে মানগুলিতে কোনও প্রতিনিধিত্বমূলক পরিবর্তন করার প্রয়োজন নেই । রেফারেন্সগুলি সমস্ত একই দেখায় - যাতে আপনি প্রতিনিধিত্বের কোনও পরিবর্তন ছাড়াই একটি IEnumerable<string>হিসাবে ব্যবহার করতে পারেন IEnumerable<object>; স্থানীয় কোডটি নিজেই জেনে রাখা দরকার না যে আপনি আদৌ মানগুলি নিয়ে কী করছেন, যতক্ষণ অবকাঠামোগত নিশ্চয়তা দিয়েছে যে এটি অবশ্যই কার্যকর হবে।

মান ধরণের জন্য, এটি কাজ করে না - একটি IEnumerable<int>হিসাবে একটি হিসাবে আচরণ করতে IEnumerable<object>, সিকোয়েন্সটি ব্যবহার করে কোডটি বক্সিং রূপান্তর করতে হবে কিনা তা জানতে হবে।

আপনি সাধারণত এই বিষয়টির জন্য আরও সাধারণত প্রতিনিধিত্ব এবং পরিচয় সম্পর্কিত এরিক লিপার্টের ব্লগ পোস্টটি পড়তে চাইতে পারেন ।

সম্পাদনা: এরিকের ব্লগ পোস্টটি আমার নিজের কাছে পুনরায় পড়ার পরে, এটি প্রতিনিধিত্ব হিসাবে পরিচয় সম্পর্কে কমপক্ষে যতটা দু'জনের সংযুক্ত রয়েছে। নির্দিষ্টভাবে:

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


5
@ কুংলি: আচ্ছা এটি কিছু কিছু সংজ্ঞায় বাস্তবায়নের বিশদ, তবে এটি সীমাবদ্ধতার অন্তর্নিহিত কারণ, আমি বিশ্বাস করি।
জন স্কিটি

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

1
স্পষ্টতই, পরিচয় সংরক্ষণ intকরা যায় না কারণ এটি একটি উপপ্রকার নয় object। একটি প্রতিনিধিত্বমূলক পরিবর্তন প্রয়োজন যে সত্য এটি এর কেবল একটি পরিণতি।
আন্দ্রে কারন

3
কীভাবে কোন অবজেক্টের উপপ্রকার নয়? সিস্টেম.ভালিউটাইপ থেকে ইন 32 টি উত্তরাধিকার সূত্রে প্রাপ্ত, যা System.Object থেকে উত্তরাধিকার সূত্রে প্রাপ্ত।
ডেভিড ক্লেম্পফনার

1
@ ডেভিডক্লেম্প্পনার আমার মনে হয় @ অ্যান্ড্রে কারন মন্তব্যটি খারাপভাবে লেখা হয়নি। যে কোনও মান ধরণের যেমন Int32দুটি উপস্থাপনামূলক ফর্ম রয়েছে, "বক্সড" এবং "আনবক্সড"। সংকলকটির একটি ফর্ম থেকে অন্য রূপে রূপান্তর করতে কোড সন্নিবেশ করতে হবে, যদিও এটি সাধারণত উত্স কোড স্তরে অদৃশ্য থাকে। কার্যত, কেবলমাত্র "বাক্সযুক্ত" ফর্মটিকে অন্তর্নিহিত সিস্টেমটির একটি উপ- objectটাইপ হিসাবে বিবেচনা করা হয় , তবে সংকলকটি স্বয়ংক্রিয়ভাবে এটির সাথে ডিল করে যখনই কোনও মান টাইপ একটি সামঞ্জস্যপূর্ণ ইন্টারফেস বা টাইপের কোনও কিছুর কাছে নির্ধারিত হয় object
স্টিভ

10

অন্তর্নিহিত প্রতিনিধিত্ব সম্পর্কে চিন্তাভাবনা করা (যদিও এটি সত্যিকার অর্থে বাস্তবায়নের বিশদ হলেও) বুঝতে পারলে এটি সম্ভবত সহজ। এখানে স্ট্রিংয়ের সংগ্রহ রয়েছে:

IEnumerable<string> strings = new[] { "A", "B", "C" };

stringsনিম্নলিখিত উপস্থাপনা হিসাবে আপনি এটি ভাবতে পারেন :

[0]: স্ট্রিং রেফারেন্স -> "এ"
[1]: স্ট্রিং রেফারেন্স -> "বি"
[2]: স্ট্রিং রেফারেন্স -> "সি"

এটি তিনটি উপাদানের সংগ্রহ যা প্রতিটি স্ট্রিংয়ের রেফারেন্স। আপনি এটি বস্তুর সংকলনে কাস্ট করতে পারেন:

IEnumerable<object> objects = (IEnumerable<object>) strings;

মূলত এটি একই প্রতিনিধিত্ব ছাড়া এখন রেফারেন্সগুলি অবজেক্ট রেফারেন্স:

[0]: অবজেক্ট রেফারেন্স -> "এ"
[1]: অবজেক্ট রেফারেন্স -> "বি"
[2]: অবজেক্ট রেফারেন্স -> "সি"

উপস্থাপনা একই। তথ্যসূত্রগুলি কেবল অন্যরকমভাবে আচরণ করা হয়; আপনি আর string.Lengthসম্পত্তিটি অ্যাক্সেস করতে পারবেন না তবে আপনি কল করতে পারেন object.GetHashCode()। এটি কীট সংগ্রহের সাথে তুলনা করুন:

IEnumerable<int> ints = new[] { 1, 2, 3 };
[0]: অন্তঃ = 1
[1]: অন্তঃ = 2
[2]: অন্তঃ = 3

এটিকে IEnumerable<object>ডেটাতে রূপান্তর করতে ইনটস বক্সিং করে রূপান্তর করতে হবে:

[0]: অবজেক্ট রেফারেন্স -> 1
[1]: অবজেক্ট রেফারেন্স -> 2
[2]: অবজেক্ট রেফারেন্স -> 3

এই রূপান্তরটির জন্য কাস্টের চেয়েও বেশি প্রয়োজন।


2
বক্সিং কেবল "বাস্তবায়ন বিশদ" নয়। শ্রেণিবদ্ধ মানের ধরণগুলি শ্রেণি অবজেক্টগুলির মতো একইভাবে সংরক্ষণ করা হয়, এবং আচরণ করা হয়, যতক্ষণ বাইরের বিশ্ব বলতে পারে ক্লাস অবজেক্টগুলির মতো। পার্থক্যটি কেবলমাত্র একটি বাক্সযুক্ত মান ধরণের সংজ্ঞা অনুসারে, thisএমন একটি কাঠামোকে বোঝায় যেগুলির ক্ষেত্রগুলি হিপ অবজেক্টগুলির মধ্যে ওভারলে দেয় যা এটি সংরক্ষণ করে rather এনকোলেসিং হিপ অবজেক্টের রেফারেন্স পাওয়ার জন্য বক্সযুক্ত মান ধরণের দৃষ্টান্তের জন্য কোনও পরিষ্কার উপায় নেই।
সুপারক্যাট

7

আমি মনে করি LSP(লিসকভ সাবস্টিটিউশন প্রিন্সিপাল) এর চূড়ান্ত বিবরণ থেকে সমস্ত কিছু শুরু হয় , যা ক্লাইমস:

যদি q (x) টি প্রকারের টি x এর অবজেক্টগুলির সম্পর্কে প্রমাণযোগ্য একটি সম্পত্তি হয় তবে Q (y) এস টাইপের এসের বস্তুগুলির ক্ষেত্রে সত্য হওয়া উচিত যেখানে এস টি-এর একটি উপ টাইপ is

তবে মান ধরণের উদাহরণস্বরূপ intবিকল্পের বিকল্প হতে পারে objectনা C#। প্রমাণ খুব সহজ:

int myInt = new int();
object obj1 = myInt ;
object obj2 = myInt ;
return ReferenceEquals(obj1, obj2);

falseআমরা যদি বস্তুর জন্য একই "রেফারেন্স" নির্ধারণ করি এমনকি এটি ফিরে আসে ।


1
আমি মনে করি আপনি সঠিক নীতিটি ব্যবহার করছেন তবে এটির কোনও প্রমাণ নেই: নীতিটি প্রয়োগ হয় না তাই এটির intএকটি উপপ্রকার objectনয়। আপনার "প্রমাণ" একটি অন্তর্বর্তী উপস্থাপনার উপর নির্ভর করে Integer, যা একটি উপপ্রকার objectএবং যার জন্য ভাষার একটি অন্তর্নিহিত রূপান্তর রয়েছে ( object obj1=myInt;প্রকৃতপক্ষে প্রসারিত হয় object obj1=new Integer(myInt))।
আন্দ্রে কারন

ভাষা বিভিন্ন ধরণের মধ্যে সঠিক ingালাইয়ের যত্ন নেয়, তবে অন্তর্নিহিত আচরণের সাথে আমরা বস্তুর সাব টাইপটি প্রত্যাশা করতে পারি না।
টিগ্রান

আমার পুরো বিষয়টি intহুবহু এটি একটি উপপ্রকার নয় object। অধিকন্তু, LSP কারণ প্রযোজ্য না myInt, obj1এবং obj2তিনটি ভিন্ন বস্তু পড়ুন: এক intএবং দুই (লুকানো) Integers।
আন্দ্রে কারন

22
@ আন্দ্রে: সি # জাভা নয়। সি # এর intকীওয়ার্ডটি ছাত্রলীগের জন্য একটি উপনাম System.Int32, যা বাস্তবে object(একটি উপনামের System.Object) একটি সাব টাইপ । আসলে, intএর বেস ক্লাসটি হ'ল System.ValueTypeকে বেস ক্লাস System.Object। নিম্নলিখিত অভিব্যক্তি মূল্যায়নের চেষ্টা করুন এবং দেখুন: typeof(int).BaseType.BaseTypeReferenceEqualsএখানে মিথ্যা প্রত্যাবর্তনের কারণটি হ'ল intদুটি পৃথক বাক্সে বাক্সযুক্ত এবং অন্য বাক্সের জন্য প্রতিটি বাক্সের পরিচয় আলাদা। সুতরাং দুটি বক্সিং অপারেশন সবসময় দুটি বস্তু উত্পাদন করে যা কখনই সাদৃশ্যযুক্ত না, বক্সের মান নির্বিশেষে।
অ্যালন গুরালেনেক

@ অ্যালোনগুরালেনেক: প্রতিটি মানের ধরণ (যেমন System.Int32বা List<String>.Enumerator) আসলে দুটি ধরণের জিনিস উপস্থাপন করে: একটি স্টোরেজ-অবস্থানের ধরণ এবং একটি হিপ-অবজেক্ট টাইপ (কখনও কখনও "বক্সযুক্ত মান প্রকার" নামে পরিচিত)। স্টোরের অবস্থানগুলি যার প্রকার থেকে প্রাপ্ত System.ValueTypeতা পূর্বেরটিকে ধরে রাখবে; যার ধরণের অনুরূপভাবে হ'ল গাদা বস্তুগুলি পরেরটি ধরে রাখে। বেশিরভাগ ভাষায়, পূর্ববর্তী থেকে প্রসারিত castালাই এবং আধুনিক থেকে পূর্বের পর্যন্ত সংকীর্ণ কাস্ট বিদ্যমান। মনে রাখবেন যে বাক্সযুক্ত মানের ধরণের মান-ধরণের স্টোরেজ অবস্থানগুলির মতো একই ধরণের বর্ণনাকারী রয়েছে ...
সুপারক্যাট

3

এটি বাস্তবায়নের বিশদে নেমে আসে: মান প্রকারগুলি রেফারেন্স ধরণের ক্ষেত্রে পৃথকভাবে প্রয়োগ করা হয়।

যদি আপনি মান প্রকারগুলিকে রেফারেন্স ধরণের হিসাবে গণ্য করতে বাধ্য করেন (উদাহরণস্বরূপ সেগুলি বক্স করুন, উদাহরণস্বরূপ একটি ইন্টারফেসের মাধ্যমে সেগুলি উল্লেখ করে) আপনি বৈকল্পিকতা পেতে পারেন।

পার্থক্যটি দেখার সহজতম উপায়টি হ'ল একটি বিবেচনা করুন Array: মান ধরণের একটি অ্যারে স্মৃতিতে স্বচ্ছলভাবে (সরাসরি) একসাথে রাখা হয়, যেখানে রেফারেন্স ধরণের অ্যারে হিসাবে কেবল মেমরির সাথে স্বরূপ রেফারেন্স (পয়েন্টার) থাকে; অবজেক্টগুলিকে নির্দেশ করা হচ্ছে আলাদাভাবে বরাদ্দ করা হয়।

অন্যান্য (সম্পর্কিত) ইস্যু (*) হ'ল (প্রায়) সমস্ত রেফারেন্সের ধরণের বৈকল্পিক উদ্দেশ্যে একই উপস্থাপনা থাকে এবং প্রকারের মধ্যে পার্থক্য সম্পর্কে অনেক কোডের প্রয়োজনের প্রয়োজন হয় না, তাই সহ-এবং বিপরীতে বৈকল্পিকতা সম্ভব (এবং সহজেই বাস্তবায়িত - প্রায়শই অতিরিক্ত ধরণের পরীক্ষার বাদ দিয়ে)।

(*) এটি একই সমস্যা হতে দেখা যেতে পারে ...

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