আমি কীভাবে IEnumerable <T> প্রয়োগ করব


124

আমি জানি যে কীভাবে জেনারিক আইএননামারেবল কার্যকর করা যায়, এর মতো:

using System;
using System.Collections;

namespace ConsoleApplication33
{
    class Program
    {
        static void Main(string[] args)
        {
            MyObjects myObjects = new MyObjects();
            myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 };
            myObjects[1] = new MyObject() { Foo = "World", Bar = 2 };

            foreach (MyObject x in myObjects)
            {
                Console.WriteLine(x.Foo);
                Console.WriteLine(x.Bar);
            }

            Console.ReadLine();
        }
    }

    class MyObject
    {
        public string Foo { get; set; }
        public int Bar { get; set; }
    }

    class MyObjects : IEnumerable
    {
        ArrayList mylist = new ArrayList();

        public MyObject this[int index]
        {
            get { return (MyObject)mylist[index]; }
            set { mylist.Insert(index, value); }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return mylist.GetEnumerator();
        }
    }
}

তবে আমি আরও লক্ষ্য করেছি যে আইনামেবলের জেনেরিক সংস্করণ রয়েছে IEnumerable<T>তবে এটি কীভাবে প্রয়োগ করা যায় তা আমি বুঝতে পারি না।

আমি যদি using System.Collections.Generic;আমার ব্যবহারের দিকনির্দেশগুলিতে যোগ করি এবং তারপরে পরিবর্তন করুন:

class MyObjects : IEnumerable

প্রতি:

class MyObjects : IEnumerable<MyObject>

এবং তারপরে রাইট ক্লিক করুন IEnumerable<MyObject>এবং নির্বাচন করুন Implement Interface => Implement Interface, ভিজ্যুয়াল স্টুডিও সহায়তার সাথে নিম্নলিখিত কোডের ব্লকটি যুক্ত করে:

IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
    throw new NotImplementedException();
}

GetEnumerator();পদ্ধতিটি থেকে জেনারিক আইনুনামেবল অবজেক্টটি ফিরিয়ে দেওয়া এখনকার মতো কাজ করে না, তাই আমি এখানে কী রাখব? সিএলআই এখন জেনেরিক বাস্তবায়ন উপেক্ষা করে এবং জেনেরিক সংস্করণে সরাসরি চলে যায় যখন ফোরচ লুপের সময় এটি আমার অ্যারের মাধ্যমে অঙ্ক করার চেষ্টা করে।

উত্তর:


149

আপনি যদি জেনেরিক সংগ্রহ যেমন List<MyObject>তার পরিবর্তে ব্যবহার করতে চান তবে আপনি ArrayListদেখতে পাবেন যে এটি List<MyObject>জেনেরিক এবং নন-জেনেরিক উভয় গণক সরবরাহ করবে যা আপনি ব্যবহার করতে পারেন।

using System.Collections;

class MyObjects : IEnumerable<MyObject>
{
    List<MyObject> mylist = new List<MyObject>();

    public MyObject this[int index]  
    {  
        get { return mylist[index]; }  
        set { mylist.Insert(index, value); }  
    } 

    public IEnumerator<MyObject> GetEnumerator()
    {
        return mylist.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

1
জেনারিক বাস্তবায়নে, ফিরে আসা this.GetEnumerator()এবং কেবল ফিরে আসার মধ্যে কি পার্থক্য রয়েছে GetEnumerator()?
ট্যানার সোয়েট

1
পছন্দ করুন
মনরো থমাস

আপনি পাশাপাশি উত্তরাধিকারী হতে পারেন Collection<MyObject>এবং তারপরে আপনাকে কোনও কাস্টম কোড লিখতে হবে না।
জন আলেক্সিউ 21

@ জা 72২ আপনি যদি ইতিমধ্যে অন্য বেস ক্লাস থেকে উত্তরাধিকারী হন এবং সংগ্রহ <মাইঅবজেক্ট> থেকে উত্তরাধিকারী না হন তবে কী হবে?
মনরো থমাস

1
@ মনরো থমাস - তারপরে আপনাকে আপনার উত্তরে প্রদর্শিত হিসাবে মোড়ানো List<T>এবং প্রয়োগ IEnumerable<T>করতে হবে।
জন আলেক্সিউ

69

আপনি সম্ভবত এর সুস্পষ্ট বাস্তবায়ন চান না IEnumerable<T>(এটি যা আপনি দেখিয়েছেন)।

ব্যবহারের স্বাভাবিক প্যাটার্ন IEnumerable<T>'s GetEnumeratorএর স্পষ্ট বাস্তবায়নের IEnumerable:

class FooCollection : IEnumerable<Foo>, IEnumerable
{
    SomeCollection<Foo> foos;

    // Explicit for IEnumerable because weakly typed collections are Bad
    System.Collections.IEnumerator IEnumerable.GetEnumerator()
    {
        // uses the strongly typed IEnumerable<T> implementation
        return this.GetEnumerator();
    }

    // Normal implementation for IEnumerable<T>
    IEnumerator<Foo> GetEnumerator()
    {
        foreach (Foo foo in this.foos)
        {
            yield return foo;
            //nb: if SomeCollection is not strongly-typed use a cast:
            // yield return (Foo)foo;
            // Or better yet, switch to an internal collection which is
            // strongly-typed. Such as List<T> or T[], your choice.
        }

        // or, as pointed out: return this.foos.GetEnumerator();
    }
}

2
যদি সামোলেকশন <টি> ইতিমধ্যে আইনিম্যুয়াল <টি> প্রয়োগ করে না, বা যদি আপনাকে সূত্রের ক্রমটিতে ফিরে আসার আগে প্রতিটি উপাদানটিতে অন্য রূপান্তর বা অন্য প্রক্রিয়াজাতকরণ প্রয়োজন হয় তবে এটি একটি ভাল সমাধান। যদি এই শর্তগুলির মধ্যে দুটিও সত্য না হয়, তবে সম্ভবত এটি.ফুস.গেটইউনমেন্টার () ফিরিয়ে দেওয়া আরও কার্যকর;
মনরো থমাস

@ মনরো থমাস: সম্মত। ওপি কী সংগ্রহ ব্যবহার করছে তা কোনও ক্লু নেই।
user7116

8
ভাল যুক্তি. তবে বাস্তবায়ন IEnumerableঅপ্রয়োজনীয় ( IEnumerable<T>ইতিমধ্যে এটি উত্তরাধিকার সূত্রে প্রাপ্ত)।
rsenna

ICollection, IEnumerable: - @rsenna এটা সত্য, তবে মনের মধ্যে এমনকি .NET ইন্টারফেসগুলি রাখা মত IList redundantly ইন্টারফেসগুলি বাস্তবায়ন, এটা পাঠযোগ্যতা জন্য সর্বজনীন ইন্টারফেস IList
ডেভিড Klempfner

@ ব্যাকওয়ার্ড_ড্যাভ আমি আসলে (এখনও) মনে করি এটি কম পাঠযোগ্য করে তোলে, যেহেতু এটি অপ্রয়োজনীয় গোলমাল যোগ করে, তবে আপনি যা বলেছিলেন তা আমি বুঝতে পেরেছি এবং মনে করি এটি একটি কার্যকর মতামত।
RSSenna

24

কেন আপনি ম্যানুয়ালি এটি করেন? yield returnপুনরাবৃত্তি পরিচালনার সম্পূর্ণ প্রক্রিয়াটি স্বয়ংক্রিয় করে তোলে। (আমি আমার ব্লগে এটিও লিখেছিলাম , সংকলক উত্পন্ন কোডটি দেখেছি )।

আপনি যদি সত্যিই এটি করতে চান তবে আপনাকে একটি জেনেরিক গণনাও ফিরিয়ে দিতে হবে। ArrayListজেনারিক না হওয়ায় আপনি আর কোনওটি ব্যবহার করতে পারবেন না । List<MyObject>পরিবর্তে এটি পরিবর্তন করুন । এটি অবশ্যই ধরে নিয়েছে যে MyObjectআপনার সংগ্রহে কেবলমাত্র টাইপের (বা উত্পন্ন ধরণের) অবজেক্ট রয়েছে ।


2
+1, এটি লক্ষ করা উচিত যে পছন্দসই প্যাটার্নটি হ'ল জেনেরিক ইন্টারফেস প্রয়োগ করা এবং স্পষ্টভাবে অ-জেনেরিক ইন্টারফেস বাস্তবায়ন করা। জেনারিক ইন্টারফেসের সবচেয়ে স্বাভাবিক সমাধান হ'ল ফলন ফেরত।
ব্যবহারকারী 7116

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

@ মনরো থমাস: আপনি ঠিক বলেছেন। লেখার আগে আমি খুব মনোযোগ দিয়ে প্রশ্নটি পড়িনি yield return। আমি ভুলভাবে ধরে নিয়েছি যে কিছু কাস্টম প্রক্রিয়াজাতকরণ রয়েছে।
অ্যান্ডারস আবেল

4

যদি আপনি জেনেরিকের সাথে কাজ করেন তবে অ্যারেলিস্টের পরিবর্তে তালিকা ব্যবহার করুন। তালিকার আপনার ঠিক মতো getEnumerator পদ্ধতি রয়েছে।

List<MyObject> myList = new List<MyObject>();

0

মাইলিস্টকে একটি হিসাবে তৈরি করুন List<MyObject>, এটি একটি বিকল্প


0

মনে রাখবেন যে অন্যভাবে IEnumerable<T>প্রয়োগ করা অলরেডি System.Collectionsহ'ল আপনার MyObjectsশ্রেণিকে System.Collectionsবেস ক্লাস ( ডকুমেন্টেশন ) হিসাবে নেওয়া:

সিস্টেম. সংগ্রহসমূহ: জেনেরিক সংগ্রহের জন্য বেস শ্রেণি সরবরাহ করে।

আমরা পরে আমাদের নিজস্ব implemenation ভার্চুয়াল ওভাররাইড করতে করতে পারেন System.Collectionsপদ্ধতি কাস্টম আচরণ প্রদান (শুধুমাত্র ClearItems, InsertItem, RemoveItem, এবং SetItemসহ Equals, GetHashCodeএবং ToStringথেকে Object)। List<T>যা সহজেই বর্ধনযোগ্য হিসাবে ডিজাইন করা হয়নি তার বিপরীতে ।

উদাহরণ:

public class FooCollection : System.Collections<Foo>
{
    //...
    protected override void InsertItem(int index, Foo newItem)
    {
        base.InsertItem(index, newItem);     
        Console.Write("An item was successfully inserted to MyCollection!");
    }
}

public static void Main()
{
    FooCollection fooCollection = new FooCollection();
    fooCollection.Add(new Foo()); //OUTPUT: An item was successfully inserted to FooCollection!
}

দয়া করে মনে রাখবেন যে collectionকাস্টম সংগ্রহের আচরণের প্রয়োজন হলে কেবল ড্রাইভ করার পরামর্শ দেওয়া হয় যা খুব কমই ঘটে। দেখতে ব্যবহার

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