এক্স থেকে y এ সহ-বৈকল্পিক অ্যারে রূপান্তর রান-টাইম ব্যতিক্রম হতে পারে


142

আমার s এর একটি private readonlyতালিকা রয়েছে । আমি পরে এই তালিকায় এস যুক্ত করব এবং সেই লেবেলগুলিকে নীচের মতো যুক্ত করব:LinkLabelIList<LinkLabel>LinkLabelFlowLayoutPanel

foreach(var s in strings)
{
    _list.Add(new LinkLabel{Text=s});
}

flPanel.Controls.AddRange(_list.ToArray());

Resharper আমাকে শো একটি সতর্কবার্তা: Co-variant array conversion from LinkLabel[] to Control[] can cause run-time exception on write operation

অনুগ্রহ করে আমাকে বুঝতে সহায়তা করুন:

  1. এর অর্থ কী?
  2. এটি একটি ব্যবহারকারীর নিয়ন্ত্রণ এবং একাধিক বস্তু সেটআপ লেবেলে অ্যাক্সেস পাবে না, সুতরাং কোড রাখার ফলে এটি প্রভাবিত করবে না।

উত্তর:


154

এর অর্থ কী এটি

Control[] controls = new LinkLabel[10]; // compile time legal
controls[0] = new TextBox(); // compile time legal, runtime exception

এবং আরও সাধারণভাবে

string[] array = new string[10];
object[] objs = array; // legal at compile time
objs[0] = new Foo(); // again legal, with runtime exception

সি # তে, আপনাকে অবজেক্টগুলির একটি অ্যারে (আপনার ক্ষেত্রে লিংক লেবেলগুলি) বেস টাইপের অ্যারে হিসাবে (এই ক্ষেত্রে, নিয়ন্ত্রণের অ্যারে হিসাবে) হিসাবে উল্লেখ করার অনুমতি দেওয়া হয়। অ্যারেতে এমন একটি অন্য অবজেক্ট বরাদ্দ করাও আইনী সংকলন বৈধ Control। সমস্যাটি হ'ল অ্যারেটি আসলে কন্ট্রোলগুলির একটি অ্যারে নয়। রানটাইমে, এটি এখনও লিংক লেবেলগুলির একটি অ্যারে। যেমন, অ্যাসাইনমেন্ট, বা লিখুন একটি ব্যতিক্রম ছুঁড়ে ফেলবে।


আমি আপনার উদাহরণ হিসাবে রানটাইম / সংকলন সময়ের পার্থক্য বুঝতে পারি তবে বিশেষ ধরণের থেকে বেস টাইপে রূপান্তর আইনী নয়? তাছাড়া আমি তালিকাটি টাইপ করেছি এবং আমি LinkLabel(বিশেষায়িত টাইপ) থেকে Control(বেস টাইপ) যাচ্ছি ।
TheVilageIdiot

2
হ্যাঁ, একটি লিংকবেল থেকে নিয়ন্ত্রণে রূপান্তর করা বৈধ তবে এটি এখানে যা ঘটছে তার মতো নয়। এটি একটি থেকে রূপান্তরিত করার বিষয়ে সতর্ক LinkLabel[]করছে Control[], যা এখনও আইনী, তবে রানটাইম সমস্যা হতে পারে। সমস্ত পরিবর্তন হয়েছে যেভাবে অ্যারেটি উল্লেখ করা হচ্ছে। অ্যারে নিজেই পরিবর্তন করা হয় না। বিষয়টি দেখুন? অ্যারে এখনও উদ্ভূত প্রকারের অ্যারে is রেফারেন্সটি বেস ধরণের অ্যারের মাধ্যমে হয় is অতএব, বেস টাইপটিতে এটিতে একটি উপাদান নির্ধারণ করা আইনী সংকলন বৈধ। তবু রানটাইম টাইপ এটি সমর্থন করবে না।
অ্যান্থনি পেগ্রাম

আপনার ক্ষেত্রে, আমি মনে করি এটি কোনও সমস্যা নয়, আপনি নিয়ন্ত্রণের তালিকায় যুক্ত করতে কেবল অ্যারেটি ব্যবহার করছেন।
অ্যান্টনি পেগ্রাম

6
যদি কারও কারও ভেবে অবাক হয় যে কেন সি # তে অ্যারেগুলি স্বতঃস্ফূর্তভাবে সমবায় করা হয়: এরিক লিপার্টের ব্যাখ্যা : এটি
ফ্রান্সসু

14

আমি অ্যান্টনি পেগ্রামের উত্তরটি পরিষ্কার করার চেষ্টা করব।

যখন বলা ধরনের মান (যেমন ফেরৎ জেনেরিক টাইপ কিছু টাইপ যুক্তি উপর covariant হয় Func<out TResult>আয় দৃষ্টান্ত TResult, IEnumerable<out T>আয় দৃষ্টান্ত T)। অর্থাৎ কিছু আয় দৃষ্টান্ত যদি TDerived, আপনি ভাল হিসাবে যেমন দৃষ্টান্ত সাথে কাজ করতে পারেন, যেন তারা ছিল TBase

জেনেরিক টাইপটি কোনও ধরণের আর্গুমেন্টের তুলনায় বিপরীত হয় যখন এটি উল্লিখিত প্রকারের মানগুলি গ্রহণ করে (যেমন উদাহরণ Action<in TArgument>স্বীকার করে TArgument)। এটি হ'ল, যদি কোনও কিছুর উদাহরণ প্রয়োজন হয় তবে TBaseআপনি উদাহরণস্বরূপ পাসও করতে পারেন TDerived

এটি বেশ যৌক্তিক বলে মনে হয় যে জেনেরিক প্রকার যা উভয়ই কিছু প্রকারের দৃষ্টান্ত গ্রহণ করে এবং ফেরত দেয় (যদি না এটি জেনেরিক ধরণের স্বাক্ষরে দু'বার সংজ্ঞায়িত করা হয় CoolList<TIn, TOut>) তবে এগুলি সম্পর্কিত ধরণের যুক্তিতে কোভারিয়েন্ট বা বিপরীত নয়। উদাহরণস্বরূপ ,। Listনেট 4 হিসাবে সংজ্ঞায়িত করা হয়েছে List<T>, না List<in T>বা নয় List<out T>

কিছু সামঞ্জস্যের কারণে মাইক্রোসফ্ট সেই যুক্তিটিকে উপেক্ষা করতে এবং তাদের মান টাইপ যুক্তির উপর অ্যারেটি কোভারিয়েন্ট তৈরি করতে পারে। হতে পারে তারা একটি বিশ্লেষণ চালিয়ে গিয়ে দেখা গেছে যে বেশিরভাগ লোকেরা কেবল অ্যারে ব্যবহার করে যেমন তারা কেবলমাত্র পঠনযোগ্য (অর্থাৎ তারা কেবল অ্যারেতে কিছু ডেটা লেখার জন্য অ্যারে প্রারম্ভকারী ব্যবহার করে) এবং যেমন সুবিধাগুলি সম্ভাব্য রানটাইম দ্বারা সৃষ্ট অসুবিধাগুলি ছাড়িয়ে যায় ত্রুটিগুলি যখন অ্যারেতে লেখার সময় কেউ কেউ covariance ব্যবহার করার চেষ্টা করবে। সুতরাং এটি অনুমোদিত তবে উত্সাহিত নয়।

আপনার মূল প্রশ্ন হিসাবে, মূল তালিকা থেকে অনুলিপি করা মানগুলি সহ list.ToArray()একটি নতুন তৈরি করে LinkLabel[]এবং (যুক্তিসঙ্গত) সতর্কতা থেকে মুক্তি পেতে আপনাকে প্রবেশ Control[]করতে হবে AddRangelist.ToArray<Control>()কাজটি করবে: তার যুক্তি হিসাবে ToArray<TSource>গ্রহণ IEnumerable<TSource>করে এবং প্রত্যাবর্তন করে TSource[]; List<LinkLabel>কেবল পঠনযোগ্য প্রয়োগ করে IEnumerable<out LinkLabel>, যা IEnumerableসর্বগ্রহকে ধন্যবাদ , IEnumerable<Control>তার যুক্তি হিসাবে গ্রহণ পদ্ধতিতে পাস করা যেতে পারে ।


11

সর্বাধিক সোজা এগিয়ে "সমাধান"

flPanel.Controls.AddRange(_list.AsEnumerable());

এখন যেহেতু আপনি সর্বজনগ্রাহীভাবে পরিবর্তন List<LinkLabel>করছেন IEnumerable<Control>তখন আর কোনও উদ্বেগের বিষয় নেই কারণ একটি গণ্যমানের সাথে কোনও আইটেম "যুক্ত" করা সম্ভব নয়।


10

সাবধানবাণী সত্য যে আপনি তাত্ত্বিক একটি যোগ করতে পারিনি কারণে Controlঅন্য কোনো তুলনায় LinkLabelকরার LinkLabel[]মাধ্যমে Control[]এটি রেফারেন্স। এটি একটি রানটাইম ব্যতিক্রম ঘটায়।

রূপান্তরটি এখানে ঘটছে কারণ এটি AddRangeগ্রহণ করে Control[]

আরও সাধারণভাবে, উদ্ভূত ধরণের একটি ধারককে বেস ধরণের ধারককে রূপান্তর করা কেবল তখনই নিরাপদ যদি আপনি পরবর্তীকালে কেবল বর্ণনামূলকভাবে ধারকটি সংশোধন করতে না পারেন। অ্যারে প্রয়োজনীয়তা পূরণ করে না।


5

সমস্যাটির মূল কারণটি অন্য উত্তরে সঠিকভাবে বর্ণিত হয়েছে, তবে সতর্কবার্তাটি সমাধান করতে আপনি সর্বদা লিখতে পারেন:

_list.ForEach(lnkLbl => flPanel.Controls.Add(lnkLbl));

2

ভিএস ২০০৮ এর সাথে আমি এই সতর্কতাটি পাচ্ছি না। এটি অবশ্যই। নেট 4.0 এ নতুন হতে হবে be
স্পষ্টকরণ: স্যাম ম্যাক্রিলের মতে এটি পুনরায় ভাগ করা যিনি একটি সতর্কতা প্রদর্শন করেন।

সি # সংকলক জানে না যে AddRangeএটিতে পাস করা অ্যারেটি সংশোধন করবে না। যেহেতু AddRangeটাইপের একটি প্যারামিটার রয়েছে তাই এটি Control[]তাত্ত্বিকভাবে অ্যারেগুলিকে একটি বরাদ্দ দেওয়ার চেষ্টা TextBoxকরতে পারে যা সত্যিকারের অ্যারের জন্য পুরোপুরি সঠিক হবে Controlতবে অ্যারেটি বাস্তবে একটি অ্যারে LinkLabelsএবং এই জাতীয় কার্যভার গ্রহণ করবে না।

সি # তে অ্যারেগুলি সহ-রূপান্তর করা মাইক্রোসফ্টের একটি খারাপ সিদ্ধান্ত ছিল। প্রথমদিকে বেইস টাইপের একটি অ্যারের থেকে একটি উত্পন্ন ধরণের অ্যারের নির্ধারণ করতে সক্ষম হওয়া ভাল ধারণা হতে পারে, এটি রানটাইম ত্রুটির দিকে পরিচালিত করতে পারে!


2
আমি এই সতর্কতাটি পুনঃশ্যাপার থেকে পেয়েছি
স্যাম ম্যাক্রিল

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