সি # তে, কেন একটি তালিকা <স্ট্রিং> বস্তু একটি তালিকা <object> ভেরিয়েবলের মধ্যে সংরক্ষণ করা যায় না


85

দেখে মনে হচ্ছে একটি তালিকা অবজেক্ট সি # তে একটি তালিকা ভেরিয়েবলে সংরক্ষণ করা যাবে না এবং এমনকি পরিষ্কারভাবে সেভাবে কাস্টও করা যায় না।

List<string> sl = new List<string>();
List<object> ol;
ol = sl;

করতে পারেন ফলাফল না পরোক্ষভাবে টাইপ রূপান্তর System.Collections.Generic.List<string>করতেSystem.Collections.Generic.List<object>

এবং তারপর...

List<string> sl = new List<string>();
List<object> ol;
ol = (List<object>)sl;

করতে পারেন ফলাফল না টাইপ রূপান্তর System.Collections.Generic.List<string>করতেSystem.Collections.Generic.List<object>

অবশ্যই, আপনি স্ট্রিং তালিকা থেকে সমস্ত কিছু টেনে এনে এবং এটি একবারে একবারে রেখে দিতে পারেন, তবে এটি একটি বরং সংশ্লেষযুক্ত সমাধান।


4
এটি সি # ৪.০ এর সাথে পরিবর্তিত হতে চলেছে, সুতরাং আপনি খুঁজছেন সমকালীনতা এবং বিপরীতমুখী হতে চান। এটি এ জাতীয় জিনিসগুলিকে এক প্রকার নিরাপদ উপায়ে অনুমতি দেবে।
জন লিডেগ্রেন

আরও বা কম সদৃশ: stackoverflow.com/questions/317335/…
জোয়েল

7
জন> সি # 4 এটির অনুমতি দেবে না। অল.এড (নতুন বস্তু ()) সম্পর্কে চিন্তা করুন;
Guillaume,

এটি জোন স্কিকেটের উত্তর এখানে: stackoverflow.com/a/2033921/1070906
JCH2k

উত্তর:


39

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

পার্শ্ব নোট হিসাবে, আমি মনে করি আপনি বিপরীত কাস্ট করতে পারবেন কিনা তা আরও তাত্পর্যপূর্ণ হবে:

List<object> ol = new List<object>();
List<string> sl;
sl = (List<string>)ol;

আমি কিছুক্ষণের মধ্যে সি # ব্যবহার করিনি, সুতরাং আমি জানি না যে এটি আইনী কিনা, তবে এই ধরণের কাস্টটি আসলে (সম্ভাব্য) কার্যকর। এই ক্ষেত্রে, আপনি আরও সাধারণ শ্রেণি (অবজেক্ট) থেকে আরও নির্দিষ্ট শ্রেণিতে (স্ট্রিং) যাচ্ছেন যা সাধারণ থেকে প্রসারিত। এইভাবে, আপনি যদি স্ট্রিংয়ের তালিকায় যুক্ত হন তবে আপনি বস্তুর তালিকার লঙ্ঘন করছেন না।

এই জাতীয় অভিনেত্রী সি # তে আইনী হলে কেউ কি জানতে বা পরীক্ষা করতে পারে?


4
আমি মনে করি আপনার উদাহরণটি একই সমস্যায় ভুগছে। যদি ওল এর মধ্যে এমন কিছু থাকে যা স্ট্রিং নয়? সমস্যাটি হ'ল তালিকার কিছু পদ্ধতি সূক্ষ্মভাবে কাজ করবে যেমন যুক্ত করা / সন্নিবেশ করানো। তবে পুনরাবৃত্তি একটি বাস্তব সমস্যা হতে পারে।
ক্রিস আম্মারম্যান

4
এরিক লিপার্টের এই বিষয় সম্পর্কে ব্লগ পোস্টগুলির একটি দুর্দান্ত সিরিজ রয়েছে: কেন এটি জেনেরিক পদ্ধতির সাথে সাম্প্রদায়িকতা এবং বৈপরীত্যের সংযোজন যুক্ত করতে কাজ করতে পারে তবে শ্রেণি পর্যায়ে আমরা যেভাবে চাই তা কখনই কাজ করতে পারে না। is.gd/3kQc
ক্রিস

@ ক্রিসআমারম্যান: যদি olএর মধ্যে কিছু থাকে যা এটি স্ট্রিং নয়, আমি মনে করি রানটাইমটিতে অভিনেতা ব্যর্থ হবে। তবে যেখানে আপনি সত্যিই সমস্যার মধ্যে পড়ে যাবেন তা যদি কাস্ট সফল হয় এবং তারপরে কিছু যুক্ত করা হয় তবে olএটি স্ট্রিং নয়। কারণ slএকই অবজেক্টের রেফারেন্স, এখন আপনার List<string>একটি স্ট্রিংবিহীন থাকবে। Addসমস্যা, যা আমি উভয়প্রান্তে সারিবদ্ধ কেন এই কোড কম্পাইল করা হবে না অনুমান, কিন্তু যদি আপনি পরিবর্তন এটা কম্পাইল হবে List<object> olথেকে IEnumerable<object> ol, যা একটি নেই Add। (আমি এটি সি # 4 এ যাচাই করেছি)
টিম গুডম্যান

এই পরিবর্তনের সাথে, এটি সংকলন করে তবে একটি ছুড়ে দেয় InvalidCastExceptionকারণ রানটাইমের ধরণ olএখনও রয়েছে List<object>
টিম গুডম্যান

36

আপনি যদি .NET 3.5 ব্যবহার করছেন তবে এনুম্যারেবল.কাস্ট পদ্ধতিটি দেখুন। এটি একটি এক্সটেনশন পদ্ধতি যাতে আপনি এটিকে তালিকায় সরাসরি কল করতে পারেন।

List<string> sl = new List<string>();
IEnumerable<object> ol;
ol = sl.Cast<object>();

এটি আপনি যা চেয়েছিলেন ঠিক তা নয় তবে কৌশলটি করা উচিত।

সম্পাদনা: জুবা দ্বারা উল্লিখিত হিসাবে, আপনি একটি তালিকা পেতে তারপরে কল করতে পারেন o.ToList ()


14

আপনি বিভিন্ন ধরণের পরামিতিগুলির সাথে জেনেরিক ধরণের মধ্যে কাস্ট করতে পারবেন না। বিশেষ জেনেরিক প্রকারগুলি একই উত্তরাধিকার গাছের অংশ গঠন করে না এবং তাই সম্পর্কহীন প্রকারের।

এই প্রাক প্রাক নেট 3.5 করতে:

List<string> sl = new List<string>();
// Add strings to sl

List<object> ol = new List<object>();

foreach(string s in sl)
{
    ol.Add((object)s);  // The cast is performed implicitly even if omitted
}

লিনক ব্যবহার:

var sl = new List<string>();
// Add strings to sl

var ol = new List<object>(sl.Cast<object>());

// OR
var ol = sl.Cast<object>().ToList();

// OR (note that the cast to object here is required)
var ol = sl.Select(s => (object)s).ToList();

11

কারণটি হ'ল জেনেরিক শ্রেণিটি List<>বেশিরভাগ উদ্দেশ্যেই বহিরাগতকে একটি সাধারণ শ্রেণি হিসাবে বিবেচনা করা হয়। যেমন আপনি যখন List<string>()বলেন সংকলকটি বলে ListString()(এতে স্ট্রিং রয়েছে)। [প্রযুক্তিগত লোক: এটি যা চলছে তার একটি চূড়ান্ত-সরল-ইংলিশ-আইএইডি সংস্করণ]

ফলস্বরূপ, স্পষ্টতই সংকলকটি তার অভ্যন্তরীণ সংগ্রহের আইটেমগুলি কাস্ট করে কোনও লিস্টস্ট্রিংকে একটি তালিকাপঞ্জিতে রূপান্তর করতে পর্যাপ্ত স্মার্ট হতে পারে না।

এজন্য রূপান্তর () এর মতো আইইনুমেবলের এক্সটেনশন পদ্ধতি রয়েছে যা আপনাকে কোনও সংগ্রহের মধ্যে সঞ্চিত আইটেমগুলির জন্য সহজেই রূপান্তর সরবরাহ করতে দেয়, যা একে অপরের থেকে কাস্টিংয়ের মতো সহজ।


6

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

পরিবর্তে আপনি এফএফ কোডটি চেষ্টা করতে চাইতে পারেন:

List<string> sl = new List<string>();
//populate sl
List<object> ol = new List<object>(sl);

বা:

List<object> ol = new List<object>();
ol.AddRange(sl);

ওল (তাত্ত্বিকভাবে) সমস্যা ছাড়াই sl এর সমস্ত বিষয়বস্তু অনুলিপি করবে।





1

এটি আসলে যাতে আপনার "অল" তালিকার বৈকল্পিকের মধ্যে কোনও বিজোড় "অবজেক্ট" রাখার চেষ্টা করবেন না (যেমনটি List<object>অনুমতি দেবে বলে মনে হয়) - কারণ আপনার কোডটি তখন ক্র্যাশ হয়ে যাবে (কারণ তালিকাটি আসলেইList<string> স্ট্রিং টাইপের অবজেক্টকে গ্রহণ করবে) )। এজন্য আপনি আপনার ভেরিয়েবলটিকে আরও সাধারণ স্পেসিফিকেশনে কাস্ট করতে পারবেন না।

জাভাতে এটি অন্যভাবে, আপনার জেনেরিকস নেই এবং পরিবর্তে সমস্ত কিছুই রানটাইমের সময় অবজেক্টের তালিকা এবং আপনি সত্যই যেকোন অদ্ভুত বিষয়টিকে আপনার অনুমিত-কঠোরভাবে টাইপ করা তালিকায় স্টাফ করতে পারেন। জাভা সমস্যার বিস্তৃত আলোচনা দেখতে "রিফাইড জেনেরিকস" অনুসন্ধান করুন ...


1

জেনেরিকের উপর এই ধরনের সমবায় সমর্থিত নয়, তবে আপনি আসলে অ্যারে দিয়ে এটি করতে পারেন:

object[] a = new string[] {"spam", "eggs"};

সি # আপনাকে রান আউট থেকে বিরত রাখতে রানটাইম চেক করে, বলুন, একটি int.োকান a


0

এখানে এমন কোনও আইলিস্টের জন্য আরও একটি প্রাক- নেট নেট 3.5 সমাধান রয়েছে যার বিষয়বস্তু স্পষ্টভাবে কাস্ট করা যায়।

public IList<B> ConvertIList<D, B>(IList<D> list) where D : B
{
    List<B> newList = new List<B>();

    foreach (D item in list)
    {
        newList.Add(item);
    }

    return newList;
}

(জুবার উদাহরণের ভিত্তিতে)


0

আমার আছে একটি:

private List<Leerling> Leerlingen = new List<Leerling>();

এবং আমি এটি সংগ্রহ করা ডেটা দিয়ে পূরণ করতে যাচ্ছিলাম List<object> যা শেষ পর্যন্ত আমার জন্য কাজ করেছিল এটি ছিল:

Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>();

.Castআর টাইপ করা আপনি একটি পেতে চান IEnumerable, যে ধরণ থেকে তারপর typecast IEnemuerableকরতে List<>আপনি চান।


0

মিঃ, পূর্ববর্তী মন্তব্যে ধন্যবাদ এটির সন্ধান করার জন্য আমি দুটি উপায় পেয়েছি। প্রথমটি উপাদানগুলির স্ট্রিংয়ের তালিকা পাচ্ছে এবং তারপরে এটি আইনমেন্টেবল অবজেক্ট তালিকায় কাস্টিং করা হচ্ছে:

IEnumerable<object> ob;
List<string> st = new List<string>();
ob = st.Cast<object>();

এবং দ্বিতীয়টি আইউনামেবল অবজেক্ট টাইপ এড়িয়ে চলেছে, কেবল স্ট্রিংকে অবজেক্ট টাইপের জন্য কাস্ট করা হচ্ছে এবং তারপরে একই বাক্যে "টু লিস্ট ()" ফাংশনটি ব্যবহার করুন:

List<string> st = new List<string>();
List<object> ob = st.Cast<object>().ToList();

আমি দ্বিতীয় উপায় আরও পছন্দ করি। আশা করি এটা কাজে লাগবে.


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