কোভেরিয়েন্স এবং বিপরীতে বৈকল্পিকের মধ্যে পার্থক্য


148

সমবায়তা এবং বৈপরীত্যের মধ্যে পার্থক্য বুঝতে আমার সমস্যা হচ্ছে।

উত্তর:


266

প্রশ্নটি হল "স্ববিরোধ ও বৈপরীত্যের মধ্যে পার্থক্য কী?"

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

সমস্ত সি # প্রকারের সেটের নিম্নলিখিত দুটি উপসেট বিবেচনা করুন। প্রথম:

{ Animal, 
  Tiger, 
  Fruit, 
  Banana }.

এবং দ্বিতীয়, এটি পরিষ্কারভাবে সম্পর্কিত সেট:

{ IEnumerable<Animal>, 
  IEnumerable<Tiger>, 
  IEnumerable<Fruit>, 
  IEnumerable<Banana> }

একটা হল ম্যাপিং দ্বিতীয় সেটে প্রথম সেট থেকে অপারেশন। অর্থাৎ প্রথম সেটে প্রতিটি টিয়ের জন্য, দ্বিতীয় সেটে সংশ্লিষ্ট টাইপটি হয় IEnumerable<T>। বা, সংক্ষিপ্ত আকারে, ম্যাপিং হয় T → IE<T>। লক্ষ্য করুন এটি একটি "পাতলা তীর"।

এতদিন আমার সাথে?

এখন একটি সম্পর্ক বিবেচনা করা যাক । প্রথম সেটে জোড়া ধরণের মধ্যে একটি কার্যক্রমে সামঞ্জস্যতার সম্পর্ক রয়েছে। প্রকারের Tigerএকটি ভেরিয়েবলের জন্য টাইপের একটি মান নির্ধারিত হতে পারে Animal, সুতরাং এই ধরণেরগুলি "অ্যাসাইনমেন্ট সামঞ্জস্যপূর্ণ" হিসাবে বলা হয়। আসুন লিখুন "ধরনের একটি মান Xধরনের একটি পরিবর্তনশীল নির্ধারিত করা যেতে পারে Yএকটি সংক্ষিপ্ত আকারে": X ⇒ Y। লক্ষ্য করুন এটি একটি "চর্বিযুক্ত তীর"।

সুতরাং আমাদের প্রথম সাবসেটে, এখানে সমস্ত অ্যাসাইনমেন্টের সামঞ্জস্যতা সম্পর্ক রয়েছে:

Tiger   Tiger
Tiger   Animal
Animal  Animal
Banana  Banana
Banana  Fruit
Fruit   Fruit

সি # 4-এ, যা নির্দিষ্ট ইন্টারফেসের কোভেরিয়েন্ট অ্যাসাইনমেন্টের সামঞ্জস্যকে সমর্থন করে, দ্বিতীয় সেটে জোড়া ধরণের মধ্যে একটি অ্যাসাইনমেন্টের সামঞ্জস্যতা সম্পর্ক রয়েছে:

IE<Tiger>   IE<Tiger>
IE<Tiger>   IE<Animal>
IE<Animal>  IE<Animal>
IE<Banana>  IE<Banana>
IE<Banana>  IE<Fruit>
IE<Fruit>   IE<Fruit>

লক্ষ্য করুন যে ম্যাপিং T → IE<T> অ্যাসাইনমেন্টের সামঞ্জস্যের অস্তিত্ব এবং দিকটি সংরক্ষণ করে । এটি, যদি X ⇒ Y, তবে এটিও সত্য IE<X> ⇒ IE<Y>

যদি আমাদের চর্বিযুক্ত তীরের দুপাশে দুটি জিনিস থাকে, তবে আমরা উভয় পক্ষকে একটি অনুরূপ সরু তীরের ডানদিকে কিছু দিয়ে প্রতিস্থাপন করতে পারি।

কোনও নির্দিষ্ট সম্পর্কের ক্ষেত্রে এই সম্পত্তি থাকা ম্যাপিংকে "কোভারিয়েন্ট ম্যাপিং" বলা হয়। এটি বোঝা উচিত: টাইগারদের একটি ক্রম ব্যবহার করা যেতে পারে যেখানে প্রাণীর একটি অনুক্রম প্রয়োজন, তবে বিপরীতটি সত্য নয়। যেখানে বাঘের ক্রম প্রয়োজন সেখানে প্রাণীর একটি ক্রম প্রয়োজনীয়ভাবে ব্যবহার করা যায় না।

এটাই সমবায়। এখন সমস্ত ধরণের সেটটির এই উপসেটটি বিবেচনা করুন:

{ IComparable<Tiger>, 
  IComparable<Animal>, 
  IComparable<Fruit>, 
  IComparable<Banana> }

এখন আমাদের প্রথম সেট থেকে তৃতীয় সেট পর্যন্ত ম্যাপিং রয়েছে T → IC<T>

সি # 4 এ:

IC<Tiger>   IC<Tiger>
IC<Animal>  IC<Tiger>     Backwards!
IC<Animal>  IC<Animal>
IC<Banana>  IC<Banana>
IC<Fruit>   IC<Banana>     Backwards!
IC<Fruit>   IC<Fruit>

অর্থাৎ ম্যাপিং T → IC<T>করেছে অস্তিত্ব সংরক্ষিত কিন্তু দিক বিপরীত নিয়োগ সামঞ্জস্য করুন। মানে, যদি X ⇒ Yতারপর, IC<X> ⇐ IC<Y>

একটি ম্যাপিং যা কোনও সম্পর্ক সংরক্ষণ করে তবে এর বিপরীত হয় তাকে কনক্র্যাভারেন্ট ম্যাপিং বলে।

আবার এটি পরিষ্কারভাবে সঠিক হওয়া উচিত। একটি ডিভাইস যা দুটি প্রাণীর তুলনা করতে পারে তা দুটি বাঘের সাথে তুলনা করতে পারে, তবে একটি ডিভাইস যা দুটি বাঘের তুলনা করতে পারে তা প্রয়োজনীয়ভাবে কোনও দুটি প্রাণীর তুলনা করতে পারে না।

সুতরাং যে সি সহভেদাংক এবং contravariance পার্থক্য # 4. সহভেদাংক অপরিবর্তিত assignability দিক। বৈপরীত্য এটি বিপরীত


4
আমার মতো কারওর জন্য উদাহরণটি সংযুক্ত করা আরও ভাল হত যেটি বোঝা যায় যা কোভেরিয়েন্ট নয় এবং কোনটি বৈষম্যমূলক নয় এবং কোনটিই নয়।
bjan

2
@ বরজিট্টা: এটি অনেকটা মিল। পার্থক্যটি হ'ল সি # নির্দিষ্ট সাইটের ভিন্নতা ব্যবহার করে এবং জাভা কল সাইট ভেরিয়েন্স ব্যবহার করে । সুতরাং জিনিসগুলির পরিবর্তনের পদ্ধতিটি একই রকম, তবে যেখানে বিকাশকারী "আমার বৈকল্পিক হওয়া দরকার এটি" ভিন্ন বলে। ঘটনাচক্রে, উভয় ভাষায় বৈশিষ্ট্যটি একই ব্যক্তির দ্বারা নির্মিত কিছু অংশে ছিল!
এরিক লিপার্ট

2
@ আশিষনেগি: তীরটি "হিসাবে ব্যবহৃত হতে পারে" হিসাবে পড়ুন। "প্রাণীকে তুলনা করতে পারে এমন একটি জিনিস বাঘের তুলনা করতে পারে এমন একটি জিনিস হিসাবে ব্যবহৃত হতে পারে"। এখন বুঝবেন?
এরিক লিপার্ট

1
@ আশিষনেগি: না, এটা ঠিক নয়। আইএননামারেবল সমবায়ীয় কারণ টি কেবলমাত্র আইমনামেবলের পদ্ধতিগুলির রিটার্নে উপস্থিত হয়। এবং আইকনপমারেবল বিপরীত কারণ টি কেবল আইকোমাপেবলের পদ্ধতিগুলির আনুষ্ঠানিক পরামিতি হিসাবে উপস্থিত হয়
এরিক লিপার্ট

2
@ আশিষনেগি: আপনি যে যৌক্তিক কারণগুলির মধ্যে এই সম্পর্কের অন্তর্গত তা সম্পর্কে আপনি ভাবতে চান to কেন আমরা রূপান্তর করতে পারেন IEnumerable<Tiger>থেকে IEnumerable<Animal>নিরাপদে? কারণ জিরাফটিকে ইনপুট করার কোনও উপায় নেই IEnumerable<Animal>। কেন আমরা একটি রূপান্তর করতে পারেন IComparable<Animal>করতে IComparable<Tiger>? কারণ জি থেকে জিরাফ বের করার কোনও উপায় নেই IComparable<Animal>। ধারণা তৈরী কর?
এরিক লিপার্ট

111

উদাহরণ দেওয়া সম্ভবত সবচেয়ে সহজ - আমি অবশ্যই তাদের স্মরণ করব।

সহভেদাংক

ক্যানোনিকাল উদাহরণ: IEnumerable<out T>,Func<out T>

আপনি এর থেকে রূপান্তর করতে পারেন IEnumerable<string>থেকে IEnumerable<object>, অথবা Func<string>করার Func<object>। মানগুলি কেবল এই বিষয়গুলি থেকে প্রকাশিত হয়

এটি কাজ করে কারণ আপনি যদি কেবলমাত্র API এর বাইরে মানগুলি নিয়ে চলেছেন এবং এটি নির্দিষ্ট (যেমন string) কিছু ফেরত চলেছে , আপনি সেই প্রত্যাশিত মানটিকে আরও সাধারণ ধরণের হিসাবে পছন্দ করতে পারেন (যেমন object)।

Contravariance

ক্যানোনিকাল উদাহরণ: IComparer<in T>,Action<in T>

আপনি এর থেকে রূপান্তর করতে পারেন IComparer<object>থেকে IComparer<string>, অথবা Action<object>করার Action<string>; মান শুধুমাত্র যেতে মধ্যে এই বস্তু।

এবার এটি কাজ করে কারণ এপিআই যদি সাধারণ কিছু (যেমন object) আশা করে তবে আপনি এটিকে আরও নির্দিষ্ট কিছু (যেমন string) দিতে পারেন ।

আরো সাধারণভাবে

আপনি একটি ইন্টারফেস থাকে, তাহলে IFoo<T>তাতে covariant হতে পারে T(যেমন কি তা মেনে নেবে যেমন IFoo<out T>যদি Tশুধুমাত্র (যেমন একটি রিটার্ন টাইপ) ইন্টারফেস মধ্যে একটি আউটপুট অবস্থানে ব্যবহার করা হয়। এটা contravariant হতে পারে T(যেমন IFoo<in T>) যদি Tশুধুমাত্র একটি ইনপুট অবস্থানে ব্যবহার করা হয় ( যেমন একটি পরামিতি প্রকার)।

এটি সম্ভাব্য বিভ্রান্তিকর হয়ে পড়ে কারণ "আউটপুট পজিশন" যেমনটি শোনা যায় তত সহজ নয় - টাইপের একটি প্যারামিটার Action<T>এখনও কেবল Tএকটি আউটপুট পজিশনে ব্যবহার করে - Action<T>যদি আপনি বুঝতে চান আমার অর্থ কি round এটি একটি "আউটপুট" যাতে মানগুলি পদ্ধতিটির প্রয়োগ থেকে কলারের কোডের দিকে যেতে পারে ঠিক যেমন কোনও ফেরতের মান পারে can সাধারণত এই ধরণের জিনিসটি আসে না, ভাগ্যক্রমে :)


1
আমার মতো কারওর জন্য উদাহরণটি সংযুক্ত করা আরও ভাল হত যেটি বোঝা যায় যা কোভেরিয়েন্ট নয় এবং কোনটি বৈষম্যমূলক নয় এবং কোনটিই নয়।
bjan

1
@ জন স্কিটি চমৎকার উদাহরণ, আমি কেবল বুঝতে পারি না "ধরণের একটি পরামিতি Action<T>এখনও কেবলমাত্র Tআউটপুট অবস্থানে ব্যবহার করে "Action<T>রিটার্ন টাইপ অকার্যকর, কিভাবে এটি Tআউটপুট হিসাবে ব্যবহার করতে পারে ? বা এর অর্থ কি এটি, কারণ এটি এমন কোনও কিছু ফেরত দেয় না যে আপনি দেখতে পাচ্ছেন যে এটি কখনই নিয়ম লঙ্ঘন করতে পারে না?
আলেকজান্ডার ডার্ক

2
আমার ভবিষ্যতের আত্মার কাছে, যিনি আবার এই দুর্দান্ত উত্তরে ফিরে আসছেন পার্থক্যটি পুনর্বিবেচনা করার জন্য, এটি আপনার পছন্দসই লাইন: "[স্বীকৃতি] কাজ করে কারণ আপনি যদি কেবলমাত্র এপিআইয়ের বাইরে মানগুলি নিয়ে চলেছেন, এবং এটি কিছু ফিরিয়ে আনবে নির্দিষ্ট (স্ট্রিংয়ের মতো), আপনি ফিরে আসা মানটিকে আরও সাধারণ ধরণের (অবজেক্টের মতো) হিসাবে আচরণ করতে পারেন।
ম্যাট ক্লিন

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

@ আলেকজান্দার ডার্ক: নিশ্চিত না কেন আমি আপনাকে আগে জবাব দিইনি; আমি এটি অস্পষ্ট সম্মত, এবং এটি স্পষ্ট করার চেষ্টা করব।
জন স্কিটি

16

আমি আশা করি যে আমার পোস্টটি বিষয়টির একটি ভাষা-অজ্ঞাতদৃষ্টি দেখতে সহায়তা করবে।

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

"ধারাবাহিকতা" অর্থ কী? ধারণাটি হ'ল উচ্চ-বদলযোগ্য প্রকারের সাথে টাইপ-নিরাপদ প্রকারের স্তরক্রম ডিজাইন করা। এই ধারাবাহিকতাটি পাওয়ার কীটি হ'ল সাব টাইপ ভিত্তিক কনফারেন্স, যদি আপনি স্ট্যাটিকালি টাইপ করা ভাষায় কাজ করেন। (আমরা এখানে একটি উচ্চ স্তরের লিসকভ সাবস্টিটিউশন নীতি (এলএসপি) নিয়ে আলোচনা করব।)

ব্যবহারিক উদাহরণ (সিউডে সিউডো কোড / অবৈধ):

  • কোভেরিয়েন্স: আসুন স্ট্রিটিক টাইপিংয়ের সাথে ডিমগুলিকে "ধারাবাহিকভাবে" রাখার পাখি ধরে নেওয়া যাক: পাখিটি যদি ডিম দেয় তবে বার্ডের সাব টাইপটি ডিমের একটি টাইপটি রাখে না? উদাহরণস্বরূপ হাঁসের ধরণটি একটি DuckEgg দেয়, তারপরে ধারাবাহিকতা দেওয়া হয়। কেন এই ধারাবাহিকতা? কারণ এই জাতীয় অভিব্যক্তিতে: Egg anEgg = aBird.Lay();এবার্ড উল্লেখটি পাখির দ্বারা বা হাঁসের উদাহরণ দ্বারা আইনত প্রতিস্থাপন করা যেতে পারে। আমরা বলি যে রিটার্নের ধরণটি প্রকারের সমান্তরাল, যেখানে স্তর () সংজ্ঞায়িত হয়। একটি সাব টাইপের ওভাররাইড আরও বিশিষ্ট টাইপ ফিরে আসতে পারে। => "তারা আরও সরবরাহ করে।"

  • বৈপরীত্য: আসুন পিয়ানোস ধরে নিই যে পিয়ানোবাদীরা স্ট্যাটিক টাইপিংয়ের সাথে "ধারাবাহিকভাবে" খেলতে পারে: পিয়ানোবাদক যদি পিয়ানো বাজান, তবে তিনি কি গ্র্যান্ডপিয়ানো বাজতে পারবেন? বরং কোনও ভার্চুসো গ্র্যান্ডপিয়ানো খেলবে না? (সতর্ক হোন; একটি মোড় আছে!) এটি বেমানান! কারণ এই জাতীয় অভিব্যক্তিতে: aPiano.Play(aPianist);পিয়ানো আইনজীবিভাবে পিয়ানো বা গ্র্যান্ডপিয়ানো উদাহরণ দিয়ে এপিওয়ানকে প্রতিস্থাপন করতে পারে না! একটি গ্র্যান্ডপিয়ানো কেবল ভার্চুওসো দ্বারা বাজানো যায়, পিয়ানোবাদীরা খুব সাধারণ! গ্র্যান্ডপিয়ানস অবশ্যই আরও সাধারণ ধরণের দ্বারা প্লেযোগ্য হবে, তারপরে নাটকটি সামঞ্জস্যপূর্ণ। আমরা বলি যে পরামিতি টাইপটি প্রকারের তুলনায় বিপরীত, যাতে প্লে () সংজ্ঞায়িত হয়। একটি সাব টাইপের ওভাররাইড আরও সাধারণ আকারের গ্রহণ করতে পারে। => "তাদের কম প্রয়োজন” "

সি # তে ফিরে আসুন:
সি # মূলত একটি স্ট্যাটিক্যালি টাইপড ল্যাঙ্গুয়েজ হওয়ায় একটি ধরণের ইন্টারফেসের "অবস্থানগুলি" যা কো-বা বিপরীত (যেমন প্যারামিটার এবং রিটার্নের ধরণের) হওয়া উচিত, সেই ধরণের ধারাবাহিক ব্যবহার / বিকাশের গ্যারান্টি হিসাবে স্পষ্টভাবে চিহ্নিত করতে হবে , LSP কাজ সূক্ষ্ম করতে। গতিশীলভাবে টাইপ করা ভাষায় এলএসপি ধারাবাহিকতা সাধারণত কোনও সমস্যা হয় না, অন্য কথায় আপনি নেট-ইন্টারফেস এবং প্রতিনিধিদের উপর সহ-এবং বিপরীত "মার্কআপ" থেকে সম্পূর্ণরূপে মুক্তি পেতে পারেন, যদি আপনি কেবল আপনার প্রকারে ডায়নামিক টাইপ ব্যবহার করেন। - তবে এটি সি # এর সেরা সমাধান নয় (আপনার সর্বজনীন ইন্টারফেসে ডায়নামিক ব্যবহার করা উচিত নয়)।

তত্ত্বের দিকে ফিরে যান:
বর্ণিত কনফারেন্স (কোভারিয়েন্ট রিটার্ন টাইপ / কনভারট্রিয়েন্ট প্যারামিটার প্রকার) হ'ল তাত্ত্বিক আদর্শ (ভাষা পান্না এবং পোল -১ দ্বারা সমর্থিত)। কিছু ওপ ভাষা (যেমন আইফেল) অন্য ধরণের ধারাবাহিকতা প্রয়োগ করার সিদ্ধান্ত নিয়েছে, esp। কোভেরিয়েন্ট প্যারামিটারের ধরণগুলি কারণ এটি তাত্ত্বিক আদর্শের চেয়ে বাস্তবতাকে আরও ভালভাবে বর্ণনা করে। স্ট্যাটিকালি টাইপ করা ভাষাগুলিতে প্রায়শই "ডাবল প্রেরণ" এবং "দর্শনার্থী" এর মতো নকশার ধরণ প্রয়োগ করে কাঙ্ক্ষিত ধারাবাহিকতা অর্জন করতে হবে। অন্যান্য ভাষাগুলি তথাকথিত "একাধিক প্রেরণ" বা একাধিক পদ্ধতি সরবরাহ করে (এটি মূলত রান সময় ফাংশন ওভারলোডগুলি নির্বাচন করা হয় , যেমন সিএলওএস সহ) বা গতিশীল টাইপিং ব্যবহার করে পছন্দসই প্রভাব পান।


আপনি বলছেন একটি সাব টাইপের ওভাররাইড আরও বিশিষ্ট প্রকারটি ফিরে আসতে পারে । তবে তা সম্পূর্ণ অসত্য। যদি Birdসংজ্ঞায়িত করা হয় public abstract BirdEgg Lay();তবে তা প্রয়োগ করা Duck : Bird আবশ্যকpublic override BirdEgg Lay(){} সুতরাং আপনার দৃ ser ়বিজ্ঞানের যে BirdEgg anEgg = aBird.Lay();কোনও প্রকারের বৈকল্পিকতা রয়েছে তা কেবল অসত্য। ব্যাখ্যার মূল বিষয় হওয়ায় পুরো পয়েন্টটি এখন চলে গেছে। আপনি কি পরিবর্তে বলতে পারবেন যে বাস্তবায়নের মধ্যে যেখানে ডাকইগি স্পষ্টভাবে বার্ডএগজি আউট / রিটার্নের ধরণে প্রেরণ করা হয়েছে সেখানে সমবায়তা বিদ্যমান? যেভাবেই হোক, দয়া করে আমার বিভ্রান্তি দূর করুন।
সুমেরে

1
এটি সংক্ষিপ্তভাবে কাটা: আপনি ঠিক বলেছেন! বিভ্রান্তির জন্য দুঃখিত. সি # তেDuckEgg Lay() কোনও বৈধ ওভাররাইড নয় এবং এটি ক্রুজ। সি # কোভেরিয়েন্ট রিটার্নের ধরণগুলিকে সমর্থন করে না, তবে জাভা পাশাপাশি সি ++ করে। আমি বরং সি #-এর মতো সিনট্যাক্স ব্যবহার করে তাত্ত্বিক আদর্শটি বর্ণনা করেছি। সি # তে আপনাকে বার্ড এবং হাঁসকে একটি সাধারণ ইন্টারফেস প্রয়োগ করতে দেওয়া হবে, যেখানে লে-কে কোভারিয়েন্ট রিটার্ন (যেমন আউট-স্পেসিফিকেশন) টাইপ হিসাবে সংজ্ঞায়িত করা হয়েছে, তারপরে বিষয়গুলি একসাথে ফিট হতে পারে! Egg Lay()
নিকো

1
"আমার ভবিষ্যতের নিজের কাছে" জোন-স্কিটের জবাব সম্পর্কে ম্যাট-ক্লেইনের মন্তব্যের একটি সাদৃশ্য হিসাবে: এখানে আমার পক্ষে সবচেয়ে ভাল গ্রহণযোগ্যতা হ'ল "তারা আরও সরবরাহ করে" (নির্দিষ্ট) এবং "তাদের কম প্রয়োজন" (নির্দিষ্ট)। "কম প্রয়োজন এবং আরও বিতরণ করুন" একটি দুর্দান্ত স্মৃতিবিজ! এটি এমন একটি কাজের সাথে সাদৃশ্যপূর্ণ যেখানে আমি কম-সুনির্দিষ্ট নির্দেশাবলীর প্রয়োজন (সাধারণ অনুরোধগুলি) প্রয়োজন এবং আরও সুনির্দিষ্ট কিছু সরবরাহ করতে পারি (প্রকৃত কাজের পণ্য) product যে কোনও উপায়ে সাব টাইপ (এলএসপি) এর ক্রম অলংকৃত।
করফুস

@ কারফাস: আপনাকে ধন্যবাদ, তবে আমার মনে আছে যে আমি অন্য উত্স থেকে "কম প্রয়োজন এবং আরও বিতরণ করুন" ধারণাটি চিত্রিত করেছি। লিউয়ের যে বইটি আমি উপরে উল্লেখ করেছি তা হতে পারে ... বা একটি নেট রক টকও হতে পারে। BTW। জাভাতে, লোকেরা স্মৃতিসৌধকে "পিইসিএস" এ হ্রাস করে, যা সরাসরি বৈকল্পিক ঘোষণার সিনট্যাকটিক পদ্ধতির সাথে সম্পর্কিত, পিইসিএস হ'ল "প্রযোজক extends, গ্রাহক super"।
নিকো

5

রূপান্তরকারী প্রতিনিধি আমাকে পার্থক্য বুঝতে সাহায্য করে।

delegate TOutput Converter<in TInput, out TOutput>(TInput input);

TOutputপ্রতিনিধিত্ব করে সহভেদাংক যেখানে একটি পদ্ধতি একটি ফেরৎ আরো নির্দিষ্ট ধরনের

TInputবিপরীতে প্রতিনিধিত্ব করে যেখানে কোনও পদ্ধতি কম নির্দিষ্ট প্রকারে পাস করা হয় ।

public class Dog { public string Name { get; set; } }
public class Poodle : Dog { public void DoBackflip(){ System.Console.WriteLine("2nd smartest breed - woof!"); } }

public static Poodle ConvertDogToPoodle(Dog dog)
{
    return new Poodle() { Name = dog.Name };
}

List<Dog> dogs = new List<Dog>() { new Dog { Name = "Truffles" }, new Dog { Name = "Fuzzball" } };
List<Poodle> poodles = dogs.ConvertAll(new Converter<Dog, Poodle>(ConvertDogToPoodle));
poodles[0].DoBackflip();

0

কো এবং কনট্রা ভেরিয়েন্স বেশ যুক্তিসঙ্গত জিনিস। ভাষা টাইপ সিস্টেম আমাদের বাস্তব জীবনের যুক্তি সমর্থন করতে বাধ্য করে। উদাহরণ দিয়ে বোঝা সহজ।

সহভেদাংক

উদাহরণস্বরূপ আপনি একটি ফুল কিনতে চান এবং আপনার শহরে আপনার দুটি ফুলের দোকান রয়েছে: গোলাপের দোকান এবং ডেইজি শপ।

আপনি যদি কাউকে জিজ্ঞাসা করেন "ফুলের দোকানটি কোথায়?" এবং কেউ আপনাকে বলবে গোলাপের দোকান কোথায়, ঠিক আছে? হ্যাঁ, কারণ গোলাপ একটি ফুল, আপনি যদি ফুল কিনতে চান তবে আপনি একটি গোলাপ কিনতে পারেন। যদি কেউ আপনাকে ডেইজি শপের ঠিকানা দিয়ে উত্তর দেয় তবে এটি একই প্রযোজ্য।

এই উদাহরণ হল সহভেদাংক : আপনি ঢালাই করার অনুমতি দেওয়া হয় A<C>থেকে A<B>, যেখানে Cএকটি উপশ্রেণী হয় B, যদি A(ফাংশন থেকে ফলে আয়) জেনেরিক মান উৎপন্ন হয়। outকোভারিয়েন্স নির্মাতাদের সম্পর্কে, এজন্য সি # কোভেরিয়েন্সের জন্য কীওয়ার্ড ব্যবহার করুন।

প্রকার:

class Flower {  }
class Rose: Flower { }
class Daisy: Flower { }

interface FlowerShop<out T> where T: Flower {
    T getFlower();
}

class RoseShop: FlowerShop<Rose> {
    public Rose getFlower() {
        return new Rose();
    }
}

class DaisyShop: FlowerShop<Daisy> {
    public Daisy getFlower() {
        return new Daisy();
    }
}

প্রশ্ন "ফুলের দোকানটি কোথায়?", উত্তরটি "গোলাপের দোকান সেখানে":

static FlowerShop<Flower> tellMeShopAddress() {
    return new RoseShop();
}

Contravariance

উদাহরণস্বরূপ আপনি আপনার গার্লফ্রেন্ডকে একটি ফুল উপহার দিতে চান এবং আপনার গার্লফ্রেন্ড কোনও ফুল পছন্দ করে। আপনি কি তাকে এমন একজন ব্যক্তি হিসাবে বিবেচনা করতে পারেন যা গোলাপকে ভালোবাসে, বা ডাইজি পছন্দ করে এমন ব্যক্তি হিসাবে? হ্যাঁ, কারণ তিনি যদি কোনও ফুল পছন্দ করেন তবে তিনি গোলাপ এবং ডেইজি উভয়কেই পছন্দ করবেন।

এই একটি উদাহরণ contravariance : আপনি ঢালাই করার অনুমতি দেওয়া করছি A<B>করার A<C>, যেখানে Cএর উপশ্রেণী হয় Bযদি, Aহ্রাস জেনেরিক মান। কনট্রাভারিয়েন্স গ্রাহকরা সম্পর্কে, এজন্য সি # বিপরীতার জন্য কীওয়ার্ডটি inব্যবহার করে।

প্রকার:

interface PrettyGirl<in TFavoriteFlower> where TFavoriteFlower: Flower {
    void takeGift(TFavoriteFlower flower);
}

class AnyFlowerLover: PrettyGirl<Flower> {
    public void takeGift(Flower flower) {
        Console.WriteLine("I like all flowers!");
    }
}

আপনি আপনার গার্লফ্রেন্ডকে বিবেচনা করছেন যিনি যে কোনও ফুলকে গোলাপ ভালবাসেন এবং তাকে একটি গোলাপ উপহার হিসাবে ভালবাসেন:

PrettyGirl<Rose> girlfriend = new AnyFlowerLover();
girlfriend.takeGift(new Rose());

লিংক

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