আমি কীভাবে একটি আইএনউম্যারেবল <T> সংগ্রহে একটি আইটেম যুক্ত করতে পারি?


405

উপরের শিরোনাম হিসাবে আমার প্রশ্ন। উদাহরণ স্বরূপ,

IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));

তবে সর্বোপরি এর ভিতরে কেবলমাত্র 1 টি আইটেম রয়েছে।

আমাদের মতো কোনও পদ্ধতি থাকতে পারে items.Add(item)?

মত List<T>


4
IEnumerable<T>শুধুমাত্র সংগ্রহ অনুসন্ধানের জন্য বোঝানো হয়েছে। এটি লিনকিউ কাঠামোর জন্য মেরুদণ্ড। এটা সবসময় যেমন কিছু অন্যান্য সংগ্রহের বিমূর্ততা হয় Collection<T>, List<T>অথবা Array। ইন্টারফেসটি কেবল এমন GetEnumeratorপদ্ধতি সরবরাহ করে যা এমন একটি উদাহরণ দেয় IEnumerator<T>যা প্রসারণযোগ্য সংগ্রহের ওয়াকিংকে একবারে সক্ষম করে। লিনকিউ এক্সটেনশন পদ্ধতিগুলি এই ইন্টারফেসের মাধ্যমে সীমাবদ্ধ। IEnumerable<T>এটি পড়ার জন্য ডিজাইন করা হয়েছে কারণ এটি একাধিক সংগ্রহের অংশগুলির একত্রিতাকে উপস্থাপন করতে পারে।
জর্দান

3
এই উদাহরণস্বরূপ, কেবল IList<T>পরিবর্তে ঘোষণা করুন IEnumerable<T>:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
নাইটওয়েল 888

উত্তর:


480

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

IEnumerable<string> ReadLines()
{
     string s;
     do
     {
          s = Console.ReadLine();
          yield return s;
     } while (!string.IsNullOrEmpty(s));
}

IEnumerable<string> lines = ReadLines();
lines.Add("foo") // so what is this supposed to do??

আপনি যা করতে পারেন তা হ'ল একটি নতুন IEnumerable অবজেক্ট (অনির্ধারিত প্রকারের) তৈরি করা হবে, যা গণনা করা হলে পুরানোটির সমস্ত আইটেম এবং আপনার নিজের কিছু সরবরাহ করবে। আপনি এটির Enumerable.Concatজন্য ব্যবহার করুন :

 items = items.Concat(new[] { "foo" });

এটি অ্যারে অবজেক্টকে পরিবর্তন করবে না (আপনি যেভাবেই অ্যারেতে আইটেমগুলি সন্নিবেশ করতে পারবেন না)। তবে এটি একটি নতুন অবজেক্ট তৈরি করবে যা অ্যারের সমস্ত আইটেম তালিকাভুক্ত করবে এবং তারপরে "ফু"। তদ্ব্যতীত, এই নতুন বস্তু অ্যারের পরিবর্তনের উপর নজর রাখবে (যেমন আপনি যখনই এটি গণনা করবেন, আপনি আইটেমগুলির বর্তমান মানগুলি দেখতে পাবেন)।


3
একটি একক মান যুক্ত করতে একটি অ্যারে তৈরি করা ওভারহেডের উপরে কিছুটা উচ্চ। একক মান কনক্যাটের জন্য একটি এক্সটেনশন পদ্ধতিটি নির্ধারণ করতে এটি আরও কিছুটা পুনরায় ব্যবহারযোগ্য।
জেয়ার্ডপাড়

4
এটি নির্ভর করে - এটির জন্য এটি মূল্যবান হতে পারে তবে আমি Concatলুপে বারবার না বলা না হলে এটি অকাল অপটিমাইজেশন বলতে প্ররোচিত হই ; এবং যদি এটি হয় তবে যাইহোক আপনার বড় সমস্যা রয়েছে, কারণ প্রতিবার আপনি Concat, আপনি আরও একটি স্তর তালিকাভুক্তকারী পাবেন - সুতরাং এটির শেষে একক কলটি MoveNextপুনরাবৃত্তির সংখ্যার সমান কলগুলির একটি শৃঙ্খলে পরিণত হবে।
পাভেল মিনায়েভ

2
@ পাভেল, হি সাধারণত এটি আমাকে বিরক্ত করে এমন অ্যারে তৈরির স্মৃতি ওভারহেড নয়। এটি অতিরিক্ত টাইপিং যা আমি বিরক্তিকর মনে করি :)।
জেয়ার্ডপাড়

2
সুতরাং আমি কিছুটা বুঝতে পারলাম আইইনুমেবল কী করে। এটি কেবলমাত্র পরিবর্তিত হওয়ার উদ্দেশ্যে নয় তা দেখতে হবে। ধন্যবাদ আপনাকে বলছি
ldsenow

7
আমি অন্বিত চিনি জন্য একটি সংযোগ বৈশিষ্ট্য অনুরোধ ছিল IEnumerable<T>ওভারলোডিং সহ C #, operator+যেমন Concat(উপায় দ্বারা, আপনি কি জানেন যে ভিবি, আপনি সূচক পারেন IEnumerableযেমন যদি এটা একটি অ্যারের ছিল - এটি ব্যবহার করে ElementAtফণা অধীন): connect.microsoft.com / ভিজ্যুয়াল স্টুডিও / প্রতিক্রিয়া /… । যদি আমরা Concatবাম এবং ডান উভয় একক আইটেম নিতে আরও দুটি ওভারলোড পেয়ে xs +=x যাই তবে এটি টাইপিং কেটে ফেলতে পারে - সুতরাং সি # 5.0 তে এটিকে অগ্রাধিকার দিতে ম্যাডসকে (টর্গারসেন) যান
পাভেল মিনায়েভ

98

প্রকারটি IEnumerable<T>এই জাতীয় ক্রিয়াকলাপ সমর্থন করে না। IEnumerable<T>ইন্টারফেসের উদ্দেশ্য হ'ল গ্রাহককে কোনও সংগ্রহের বিষয়বস্তু দেখার অনুমতি দেওয়া। মানগুলি পরিবর্তন করতে নয়।

আপনি যখন .ToList মত অপারেশন না ()। যোগ করুন () যদি আপনি একটি নতুন তৈরি করছেন List<T>এবং যে তালিকায় একটি মান যোগ। এটির মূল তালিকার কোনও সংযোগ নেই।

আপনি যা করতে পারেন তা হ'ল IEnumerable<T>যুক্ত মান সহ একটি নতুন তৈরি করতে এক্সটেনশন পদ্ধতি যুক্ত করুন।

items = items.Add("msg2");

এমনকি এই ক্ষেত্রে এটি আসল IEnumerable<T>বস্তুটি সংশোধন করবে না । এটিতে একটি রেফারেন্স রেখে এটি যাচাই করা যেতে পারে। উদাহরণ স্বরূপ

var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");

এই ক্রিয়াকলাপের পরে চলক টেম্প কেবল মানগুলির সেটে কেবল একটি একক উপাদান "foo" এর সাথে একটি গণনাযোগ্য রেফারেন্স দেবে যখন আইটেমগুলি "foo" এবং "বার" এর সাথে পৃথক গণনার উল্লেখ করবে।

সম্পাদনা

আমি দৃts়তার সাথে ভুলে যাচ্ছি যে অ্যাড কোনও সাধারণ এক্সটেনশন পদ্ধতি নয় IEnumerable<T>কারণ এটি প্রথমটি যা আমি সংজ্ঞায়িত করি। এটা এখানে

public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
  foreach ( var cur in e) {
    yield return cur;
  }
  yield return value;
}

12
এটিকে বলা হয় Concat:)
পাভেল মিনায়েভ

3
@ পাভেল, এটি উল্লেখ করার জন্য ধন্যবাদ এমনকি কনক্যাট কাজ করবে না কারণ এটি অন্য একটি অনুমিত <টি> নেয়। আমি আমার প্রকল্পগুলিতে আমি যে সাধারণ বর্ধিত পদ্ধতিটি সংজ্ঞায়িত করেছি তা আটকানো হয়েছে।
জেয়ার্ডপাড়

10
Addযদিও আমি এটি কল করব না , কারণ Addকার্যত অন্য কোনও। নেট টাইপ (কেবল সংগ্রহ নয়) সংগ্রহটি স্থানান্তরিত করে। হতে পারে With? অথবা এটি এমনকি আরও একটি ওভারলোড হতে পারে Concat
পাভেল মিনায়েভ

4
আমি সম্মতি Concatজানাই যে ওভারলোড সম্ভবত একটি ভাল পছন্দ হতে পারে কারণ Addসাধারণত পরিবর্তনের বিষয়টি বোঝায়।
ড্যান আব্রামভ

15
শরীরের মধ্যে পরিবর্তন সম্পর্কে কি return e.Concat(Enumerable.Repeat(value,1));?
রায় টিঙ্কার

58

পরিবর্তে আপনি ইন্টারফেস ব্যবহার ICollection<T>বা বিবেচনা বিবেচনা করেছেন IList<T>, এগুলি খুব কারণেই বিদ্যমান যে আপনি কোনও Addপদ্ধতিতে থাকতে চান IEnumerable<T>

IEnumerable<T>কোনও ধরণের উপস্থিতি হিসাবে 'চিহ্নিত' করতে ব্যবহৃত হয় ... ভাল, গণনাযোগ্য বা আইটেমগুলির কেবল একটি ক্রম অগত্যা অন্তর্নিহিত বস্তু আইটেমগুলি যোগ / অপসারণ সমর্থন করে কিনা তার কোনও গ্যারান্টি না দিয়ে। এছাড়াও মনে রাখবেন যে এই ইন্টারফেসগুলি কার্যকর করে IEnumerable<T>যাতে আপনি যে সমস্ত এক্সটেনশন পদ্ধতিগুলি পান সেগুলি পান IEnumerable<T>


31

এক দম্পতি সংক্ষিপ্ত, মিষ্টি এক্সটেনশন পদ্ধতি উপর IEnumerableএবং IEnumerable<T>আমার জন্য এটি একটি করুন:

public static IEnumerable Append(this IEnumerable first, params object[] second)
{
    return first.OfType<object>().Concat(second);
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second)
{
    return first.Concat(second);
}   
public static IEnumerable Prepend(this IEnumerable first, params object[] second)
{
    return second.Concat(first.OfType<object>());
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second)
{
    return second.Concat(first);
}

মার্জিত (ভাল, অ-জেনেরিক সংস্করণগুলি বাদে)। খুব খারাপ এই পদ্ধতিগুলি ছাত্রলীগে নেই।


প্রথম প্রিপেন্ড পদ্ধতিটি আমাকে একটি ত্রুটি দিচ্ছে। "'অবজেক্ট []' তে 'কনক্যাট' এবং সেরা এক্সটেনশন পদ্ধতি ওভারলোড 'সিস্টেমের জন্য সংজ্ঞা নেই। অনুমিত <টি উত্স>) 'এর কিছু অবৈধ যুক্তি রয়েছে "
টিম নিউটন

@ টিমনিউটন আপনি এটি ভুল করছেন। কে জানে কেন, ত্রুটি কোডের এই স্নিপেট থেকে কেউ বলতে পারে না। প্রতিলিপি: সর্বদা ব্যতিক্রমটি ধরুন এবং ToString()এটিতে চেষ্টা করুন, কারণ এটি আরও ত্রুটির বিশদটি ধারণ করে। আমি অনুমান করব যে আপনি include System.Linq;আপনার ফাইলের শীর্ষে নেই, তবে কে জানে? এটি নিজে থেকে নির্ধারণের চেষ্টা করুন, একটি ন্যূনতম প্রোটোটাইপ তৈরি করুন যা একই ত্রুটিটি প্রদর্শন করে যদি আপনি না পারেন এবং তারপরে কোনও প্রশ্নে সহায়তা চাইতে পারেন।

আমি ঠিক উপরের কোডটি অনুলিপি করে আটকালাম। প্রিপেন্ড ব্যতীত সমস্তই ঠিকঠাক কাজ করে যা আমার উল্লেখ করা ত্রুটিটি দিচ্ছে। এটি কোনও রানটাইম ব্যতিক্রম নয় এটি একটি সংকলন সময় ব্যতিক্রম।
টিম নিউটন

@ টিমনিউটন: আমি জানি না যে আপনি এটি সম্পর্কে কী বলছেন তা পুরোপুরি কার্যকর হয় আপনি সম্ভবত স্পষ্টতই ভুলভাবে সম্পাদনার পরিবর্তনগুলি উপেক্ষা করছেন এখন আমার পথে যেতে হবে, শুভদিন, স্যার।

এটি আমাদের পরিবেশ সম্পর্কে কিছু আলাদা হতে পারে। আমি VS2012 এবং .NET 4.5 ব্যবহার করছি। এটির জন্য আর আর সময় নষ্ট করবেন না আমি কেবল ভেবেছিলাম যে আমি উল্লেখ করব যে উপরের কোডটির সাথে একটি সমস্যা রয়েছে, যদিও একটি ছোট একটিও। আমি এই উত্তরটিকে যেকোন উপায়েই এর উপকারী হিসাবে তুলে ধরেছি। ধন্যবাদ।
টিম নিউটন

25

। নেট কোরটিতে একটি পদ্ধতি রয়েছে Enumerable.Appendযা হুবহু এটি করে।

পদ্ধতির উত্স কোডটি গিটহাবটিতে উপলব্ধ। .... বাস্তবায়ন (অন্যান্য উত্তরের পরামর্শের চেয়ে আরও পরিশীলিত) একটি মূল্যবান :)।


3
এটি কেবলমাত্র মূল নয়, কাঠামোটিও 7.7.১ এবং আরও নতুন: ডকস.মাইক্রোসফট.ইন- ইউএস
ডটনেট

নোট করুন যে প্রিপেন্ডেরও উপস্থিত রয়েছে: ডকস.মাইক্রোসফট
en-

22

কোনও আইনিম্যারেবল এতে আইটেম যুক্ত করতে সমর্থন করে না।

আপনি 'বিকল্প' হ'ল:

var List = new List(items);
List.Add(otherItem);

4
আপনার পরামর্শটি একমাত্র বিকল্প নয়। উদাহরণস্বরূপ, আইকোলিকেশন এবং আইলিস্ট উভয়ই এখানে যুক্তিসঙ্গত বিকল্প।
জেসন

6
তবে আপনি তাত্ক্ষণিকভাবে পারবেন না।
পল ভ্যান ব্রেঙ্ক

16

দ্বিতীয় বার্তা যুক্ত করতে আপনার প্রয়োজন -

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})

1
তবে আপনার আইকন অবজেক্টে কনক্যাট পদ্ধতির ফলাফলও অর্পণ করতে হবে।
টমাসজ প্রিজিচোডজকি

1
হ্যাঁ, টমাসজ আপনি ঠিক বলেছেন। আমি আইটেমগুলিতে সম্মিলিত মান নির্ধারণ করতে সর্বশেষ অভিব্যক্তিটি পরিবর্তন করেছি।
আমল

8

কেবলমাত্র আপনি List<T>বলেছিলেন যে আইটেমগুলিই আপনি যুক্ত করতে পারবেন না, তবে যদি আপনি কোনও আইটেম যুক্ত করেন (বা অন্য কোনও অ-পঠনযোগ্য কেবলমাত্র সংগ্রহের জন্য) আপনার কাছে বিদ্যমান একটি এনুমरेटर রয়েছে, তবে শনাক্তকারীকে অবৈধ করা হবে ( InvalidOperationExceptionতারপরে নিক্ষেপ করা হবে)।

যদি আপনি কোনও ধরণের ডেটা ক্যোয়ারী থেকে ফলাফল একত্রিত করে থাকেন তবে আপনি Concatএক্সটেনশন পদ্ধতিটি ব্যবহার করতে পারেন :

সম্পাদনা করুন: আমি প্রথমটিতে Unionউদাহরণটিতে এক্সটেনশনটি ব্যবহার করেছি , যা সত্যই সঠিক নয়। ওভারল্যাপিং কোয়েরিতে ফলাফলগুলি সদৃশ হয় না তা নিশ্চিত করতে আমার অ্যাপ্লিকেশন এটিকে ব্যাপকভাবে ব্যবহার করে।

IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);

8

আমি কেবল এখানে বলতে এসেছি, Enumerable.Concatএক্সটেনশন পদ্ধতি বাদে , Enumerable.Append.NET কোর 1.1.1 তে নামকরণ করা অন্য পদ্ধতি রয়েছে । পরেরটি আপনাকে একটি একক আইটেমকে বিদ্যমান অনুক্রমের সাথে যুক্ত করতে দেয়। সুতরাং আমলের উত্তরও যেমন লেখা যায় তেমন

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));

তবুও, দয়া করে নোট করুন যে এই ফাংশনটি ইনপুট ক্রমটি পরিবর্তন করবে না, এটি কেবল একটি মোড়ক দেয় যা প্রদত্ত ক্রম এবং সংযুক্ত আইটেমকে একসাথে রেখে দেয়।


4

অন্যরা ইতিমধ্যে আপনি কেন আইটেম যুক্ত করতে পারবেন না (এবং না করা উচিত!) সে সম্পর্কে দুর্দান্ত ব্যাখ্যা দিয়েছেন IEnumerable। আমি কেবল যুক্ত করব যে আপনি যদি এমন একটি ইন্টারফেসের কোডিং চালিয়ে যেতে চান যা কোনও সংগ্রহকে উপস্থাপন করে এবং একটি অ্যাড পদ্ধতি চায়, আপনার কোড করা উচিত ICollectionবা IList। একটি যুক্ত বোনানজা হিসাবে, এই ইন্টারফেস প্রয়োগ করে IEnumerable


1

তুমি এটি করতে পারো.

//Create IEnumerable    
IEnumerable<T> items = new T[]{new T("msg")};

//Convert to list.
List<T> list = items.ToList();

//Add new item to list.
list.add(new T("msg2"));

//Cast list to IEnumerable
items = (IEnumerable<T>)items;

8
এই প্রশ্নের উত্তর 5 বছর আগে আরও সম্পূর্ণ ফ্যাশনে দেওয়া হয়েছিল। কোনও প্রশ্নের উত্তরের উত্তরের উদাহরণ হিসাবে গ্রহণযোগ্য উত্তরটি দেখুন।
pquest

1
সর্বশেষ লাইনটি ছিল: আইটেম = (আইনিম্যুয়াল <টি>) তালিকা;
বেলেন মার্টিন

0

এটি করার সহজ উপায় সহজভাবে

IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");

তারপরে আপনি আইইনুমেবল হিসাবে তালিকাটিও ফিরে আসতে পারেন কারণ এটি আইইনুমেবল ইন্টারফেস প্রয়োগ করে


0

আপনি যদি IEnumerable<int> Ones = new List<int>(); তখন নিজের বস্তুটি তৈরি করেন তবে আপনি এটি করতে পারেন((List<int>)Ones).Add(1);


-8

অবশ্যই, আপনি পারবেন (আমি আপনার টি-ব্যবসায় একদিকে রেখে যাচ্ছি):

public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
    List<string> list = items.ToList();
    string obj = "";
    list.Add(obj);

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