সি # তে ব্যবহারের ফলন কীওয়ার্ডটি কী?


827

ইন কীভাবে আমি প্রকাশ IList <মাত্র একটি টুকরা> উত্তর প্রশ্নে এক নিম্নলিখিত কোড স্নিপেট ছিল:

IEnumerable<object> FilteredList()
{
    foreach(object item in FullList)
    {
        if(IsItemInPartialList(item))
            yield return item;
    }
}

ফলন কীওয়ার্ডটি সেখানে কী করে? আমি এটি কয়েকটি জায়গায় এবং অন্য একটি প্রশ্নে উল্লেখ করেছি, তবে এটি আসলে কী করে তা আমি খুব একটা বুঝতে পারি নি। আমি এক থ্রেড অন্য ফলনের অর্থে ফলন চিন্তা করতে অভ্যস্ত, কিন্তু এখানে প্রাসঙ্গিক বলে মনে হয় না।


এটি সম্পর্কে কেবল এমএসডিএন লিংকটিই
বিকাশকারী

14
এটি অবাক করা কিছু নয়। বিভ্রান্তি এ থেকে আসে যে আমরা "ফিরতি" দেখতে একটি ফাংশন আউটপুট হিসাবে শর্তযুক্ত যখন "ফলন" এর আগে হয় না।
ল্যারি

4
আমি
ডকগুলি

উত্তর:


737

মূল yieldশব্দটি এখানে বেশ কিছু করে।

ফাংশনটি এমন একটি বস্তু দেয় যা IEnumerable<object>ইন্টারফেস প্রয়োগ করে । যদি কোনও কলিং ফাংশন foreachএই অবজেক্টটির উপরে প্রবেশ শুরু করে, ফাংশনটি "ফলন" না হওয়া পর্যন্ত আবার কল করা হয়। এটি সি # 2.0 তে প্রবর্তিত সিনট্যাকটিক চিনি । পূর্ববর্তী সংস্করণগুলিতে আপনাকে এ জাতীয় জিনিসগুলি তৈরি করতে আপনার নিজস্ব IEnumerableএবং IEnumeratorঅবজেক্ট তৈরি করতে হয়েছিল ।

এর মতো কোড বোঝার সবচেয়ে সহজ উপায় হ'ল একটি উদাহরণ টাইপ করুন, কিছু ব্রেকপয়েন্ট সেট করুন এবং দেখুন কী ঘটে। এই উদাহরণ দিয়ে পদক্ষেপ চেষ্টা করুন:

public void Consumer()
{
    foreach(int i in Integers())
    {
        Console.WriteLine(i.ToString());
    }
}

public IEnumerable<int> Integers()
{
    yield return 1;
    yield return 2;
    yield return 4;
    yield return 8;
    yield return 16;
    yield return 16777216;
}

আপনি উদাহরণের মধ্য দিয়ে পদক্ষেপ Integers()নিলে আপনি ফিরে আসার জন্য প্রথম কলটি পেয়ে যাবেন 1। দ্বিতীয় কলটি ফিরে আসে 2এবং লাইনটি yield return 1আবার কার্যকর হয় না।

এখানে একটি বাস্তব জীবনের উদাহরণ:

public IEnumerable<T> Read<T>(string sql, Func<IDataReader, T> make, params object[] parms)
{
    using (var connection = CreateConnection())
    {
        using (var command = CreateCommand(CommandType.Text, sql, connection, parms))
        {
            command.CommandTimeout = dataBaseSettings.ReadCommandTimeout;
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    yield return make(reader);
                }
            }
        }
    }
}

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

110
আপনি yield break;যখন আর কোনও আইটেম ফিরিয়ে দিতে চান না তখন আপনি ব্যবহার করতে পারেন তা উল্লেখযোগ্য ।
ররি

7
yieldএকটি কীওয়ার্ড নয়। যদি তা হয় তবে আমি শনাক্তকারী হিসাবে int yield = 500;
ফলনটি

5
@ ব্র্যান্ডিন কারণ এটি যে সমস্ত প্রোগ্রামিং ভাষা দুটি ধরণের কীওয়ার্ডকে সংরক্ষিত এবং প্রাসঙ্গিক সমর্থন করে। ফলন পরবর্তী বিভাগে আসে যার কারণে আপনার কোড সি # সংকলক দ্বারা নিষিদ্ধ করা হয়নি। এখানে আরও বিশদ: ericlippert.com/2009/05/11/reided-and-contextual-keyवर्ड আপনি জানতে পেরে শিহরিত হবেন যে এমন একটি সংরক্ষিত শব্দও রয়েছে যা কোনও ভাষার দ্বারা কীওয়ার্ড হিসাবে স্বীকৃত নয়। যেমন জাভাতে গেটো এখানে আরও বিশদ: স্ট্যাকওভারফ্লো
আরবিটি

6
'If a calling function starts foreach-ing over this object the function is called again until it "yields"'। আমার কাছে ঠিক শোনাচ্ছে না "পথচারীদের কাছে গাড়ি ফলন করে" এর পরিবর্তে আমি সর্বদা "ফসলের প্রচুর ফলন দেয়" প্রসঙ্গে সি # ফলনের কীওয়ার্ডটি ভেবেছিলাম।
জ্যাক

369

পুনরাবৃত্তির। এটি "কভারের নীচে" একটি রাষ্ট্রীয় মেশিন তৈরি করে যা স্মরণ করে যে আপনি ফাংশনের প্রতিটি অতিরিক্ত চক্রে ছিলেন এবং সেখান থেকে উঠেছেন icks


209

ফলনের দুটি দুর্দান্ত ব্যবহার রয়েছে,

  1. এটি অস্থায়ী সংগ্রহ তৈরি না করে কাস্টম পুনরাবৃত্তি সরবরাহ করতে সহায়তা করে।

  2. এটি রাষ্ট্রীয় পুনরাবৃত্তি করতে সহায়তা করে। এখানে চিত্র বর্ণনা লিখুন

উপরোক্ত দুটি পয়েন্টকে আরও প্রদর্শনের জন্য ব্যাখ্যা করার জন্য, আমি একটি সাধারণ ভিডিও তৈরি করেছি যা আপনি এটি এখানে দেখতে পারেন


13
ভিডিওটি আমাকে পরিষ্কারভাবে বুঝতে সাহায্য করে yield। @ শিবপ্রসাদকৈরালার কোড প্রকল্পের নিবন্ধটি সি # ফলনের ব্যবহার কী? একই ব্যাখ্যার একটি ভাল উৎস
Dush

আমি একটি তৃতীয় পয়েন্ট হিসাবে যুক্ত করব যা yieldএকটি কাস্টম আইইনুমরেটর তৈরির "দ্রুত" উপায় (বরং ক্লাস আইইনমিটার ইন্টারফেস প্রয়োগ করে)।
মিঃ টুরকোস

আমি আপনার ভিডিও শিবপ্রসাদ দেখেছি এবং ফলন কীওয়ার্ডের ব্যবহারটি স্পষ্টভাবে ব্যাখ্যা করেছি।
টোর অরস্টাদ

ভিডিওটির জন্য ধন্যবাদ !. খুব ভালভাবে ব্যাখ্যা!
রোব্লোগিক

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

135

সম্প্রতি রেমন্ড চেন ফলন কীওয়ার্ডের উপর নিবন্ধগুলির একটি আকর্ষণীয় সিরিজও চালিয়েছিলেন।

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


এটিতে ভোট দেওয়া দরকার। মিষ্টি কীভাবে সে অপারেটর এবং ইন্টার্নালগুলির উদ্দেশ্য ব্যাখ্যা করে।
sajidnizami

3
অংশ 1 "ফলন ফেরতের" সিনট্যাকটিক চিনির ব্যাখ্যা করে। দুর্দান্ত ব্যাখ্যা!
ভয়ঙ্কর ওয়েইস

99

আপাতদৃষ্টিতে ফলন রিটার্ন একটি হল .NET একটি ফিরতে চিনি IEnumerable

ফলন ছাড়াই সংগ্রহের সমস্ত আইটেম একবারে তৈরি করা হয়:

class SomeData
{
    public SomeData() { }

    static public IEnumerable<SomeData> CreateSomeDatas()
    {
        return new List<SomeData> {
            new SomeData(), 
            new SomeData(), 
            new SomeData()
        };
    }
}

ফলন ব্যবহার করে একই কোড, এটি আইটেম অনুসারে আইটেমটি ফিরিয়ে দেয়:

class SomeData
{
    public SomeData() { }

    static public IEnumerable<SomeData> CreateSomeDatas()
    {
        yield return new SomeData();
        yield return new SomeData();
        yield return new SomeData();
    }
}

ফলন ব্যবহারের সুবিধা হ'ল যদি আপনার ডেটা গ্রাস করে ফাংশনটি কেবল সংগ্রহের প্রথম আইটেমের প্রয়োজন হয়, বাকি আইটেমগুলি তৈরি করা হবে না।

ফলন অপারেটর যেমন দাবি করা হয় তেমন আইটেম তৈরির অনুমতি দেয়। এটি এটি ব্যবহারের একটি ভাল কারণ।


40

yield returnগণনাকারীদের সাথে ব্যবহৃত হয়। ফলন বিবরণের প্রতিটি কলের উপরে, কলকে নিয়ন্ত্রণ ফিরিয়ে দেওয়া হয় তবে এটি নিশ্চিত করে যে কলির অবস্থা বজায় থাকবে। এ কারণে, যখন কলার পরবর্তী উপাদানটি গণনা করে, তখনই বিবৃতি দেওয়ার পরপরই বিবৃতি থেকে কলি পদ্ধতিতে এটি কার্যকর করা হয় yield

আসুন এটি একটি উদাহরণ দিয়ে বোঝার চেষ্টা করি। এই উদাহরণস্বরূপ, প্রতিটি লাইনের সাথে সামঞ্জস্য রেখে আমি মৃত্যুদন্ড কার্যকর করার ক্রমটি উল্লেখ করেছি।

static void Main(string[] args)
{
    foreach (int fib in Fibs(6))//1, 5
    {
        Console.WriteLine(fib + " ");//4, 10
    }            
}

static IEnumerable<int> Fibs(int fibCount)
{
    for (int i = 0, prevFib = 0, currFib = 1; i < fibCount; i++)//2
    {
        yield return prevFib;//3, 9
        int newFib = prevFib + currFib;//6
        prevFib = currFib;//7
        currFib = newFib;//8
    }
}

এছাড়াও, প্রতিটি গণনার জন্য রাজ্য বজায় রাখা হয়। মনে করুন, Fibs()পদ্ধতিতে আমার অন্য একটি কল রয়েছে তবে এর জন্য রাষ্ট্রটি পুনরায় সেট করা হবে।


2
prevFib = 1 সেট করুন - প্রথম ফিবোনাচি সংখ্যাটি "1", একটি "0" নয়
ফুবু

31

স্বজ্ঞাতভাবে, কীওয়ার্ডটি এটি না রেখে ফাংশন থেকে একটি মান ফেরত দেয়, যেমন আপনার কোডের উদাহরণে এটি বর্তমান itemমানটি দেয় এবং তারপরে লুপটি পুনরায় শুরু করে। আরও আনুষ্ঠানিকভাবে, এটি সংকলক দ্বারা পুনরাবৃত্তির কোড তৈরি করতে ব্যবহৃত হয় । আইট্রেটারগুলি হ'ল ফাংশন যা প্রত্যাবর্তন IEnumerableকরে। দুটিই MSDN বিভিন্ন হয়েছে প্রবন্ধ তাদের সম্পর্কে।


4
ঠিক আছে, সুনির্দিষ্টভাবে বলতে গেলে এটি লুপটি পুনরায় শুরু করে না, পিতামাতাকে "পুনরাবৃত্ত.নেক্সট ()" না বলা পর্যন্ত এটি বিরতি দেয়।
অ্যালেক্স

8
@জিবিট সেজন্য আমি "স্বজ্ঞাত" এবং "আরও আনুষ্ঠানিকভাবে" ব্যবহার করেছি used
কনরাড রুডল্ফ

31

একটি তালিকা বা অ্যারে বাস্তবায়ন সমস্ত আইটেম তত্ক্ষণাত লোড করে যেখানে ফলন বাস্তবায়ন একটি মুলতুবি প্রয়োগের সমাধান সরবরাহ করে।

অনুশীলনে, কোনও অ্যাপ্লিকেশনটির রিসোর্স খরচ হ্রাস করার জন্য প্রয়োজন হিসাবে ন্যূনতম পরিমাণ কাজ সম্পাদন করা প্রায়শই বাঞ্ছনীয়।

উদাহরণস্বরূপ, আমাদের একটি অ্যাপ্লিকেশন থাকতে পারে যা একটি ডাটাবেস থেকে কয়েক মিলিয়ন রেকর্ড প্রক্রিয়া করে। যখন আমরা একটি স্থগিতিত মৃত্যুদন্ড কার্যকর করা পুল-ভিত্তিক মডেলটিতে IEnumerable ব্যবহার করি তখন নিম্নলিখিত সুবিধাগুলি অর্জন করতে পারে:

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

উত্পাদনের তুলনায় প্রথমে একটি সংগ্রহ তৈরির তালিকার মধ্যে একটি তুলনা এখানে রয়েছে।

তালিকার উদাহরণ

    public class ContactListStore : IStore<ContactModel>
    {
        public IEnumerable<ContactModel> GetEnumerator()
        {
            var contacts = new List<ContactModel>();
            Console.WriteLine("ContactListStore: Creating contact 1");
            contacts.Add(new ContactModel() { FirstName = "Bob", LastName = "Blue" });
            Console.WriteLine("ContactListStore: Creating contact 2");
            contacts.Add(new ContactModel() { FirstName = "Jim", LastName = "Green" });
            Console.WriteLine("ContactListStore: Creating contact 3");
            contacts.Add(new ContactModel() { FirstName = "Susan", LastName = "Orange" });
            return contacts;
        }
    }

    static void Main(string[] args)
    {
        var store = new ContactListStore();
        var contacts = store.GetEnumerator();

        Console.WriteLine("Ready to iterate through the collection.");
        Console.ReadLine();
    }

কনসোল আউটপুট
যোগাযোগের তালিকাভুক্ত স্টোর: যোগাযোগ তৈরি করা হচ্ছে 1 যোগাযোগের
তালিকাভুক্ত স্টোর: যোগাযোগ তৈরি করা হচ্ছে 2
যোগাযোগলিস্টস্টোর: যোগাযোগ তৈরি করা 3
সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে প্রস্তুত to

দ্রষ্টব্য: তালিকায় একটি আইটেম না চেয়েও পুরো সংগ্রহটি মেমরিতে লোড হয়েছিল

ফলন উদাহরণ

public class ContactYieldStore : IStore<ContactModel>
{
    public IEnumerable<ContactModel> GetEnumerator()
    {
        Console.WriteLine("ContactYieldStore: Creating contact 1");
        yield return new ContactModel() { FirstName = "Bob", LastName = "Blue" };
        Console.WriteLine("ContactYieldStore: Creating contact 2");
        yield return new ContactModel() { FirstName = "Jim", LastName = "Green" };
        Console.WriteLine("ContactYieldStore: Creating contact 3");
        yield return new ContactModel() { FirstName = "Susan", LastName = "Orange" };
    }
}

static void Main(string[] args)
{
    var store = new ContactYieldStore();
    var contacts = store.GetEnumerator();

    Console.WriteLine("Ready to iterate through the collection.");
    Console.ReadLine();
}

কনসোল আউটপুট
সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে প্রস্তুত।

দ্রষ্টব্য: সংগ্রহটি মোটেও কার্যকর করা হয়নি। এটি আইইনুমেবলের "স্থগিত কার্যকরকরণ" প্রকৃতির কারণে। কোনও আইটেম তৈরি করা তখনই ঘটবে যখন এটি সত্যই প্রয়োজন হয়।

সংগ্রহের পুনরায় কল করুন এবং সংগ্রহের মধ্যে প্রথম পরিচিতিটি আনার সময় আচরণটি বাতিল করি।

static void Main(string[] args)
{
    var store = new ContactYieldStore();
    var contacts = store.GetEnumerator();
    Console.WriteLine("Ready to iterate through the collection");
    Console.WriteLine("Hello {0}", contacts.First().FirstName);
    Console.ReadLine();
}

কনসোল আউটপুট
সংগ্রহের মাধ্যমে পুনরাবৃত্তি করতে প্রস্তুত
যোগাযোগইয়েলস্টোর: যোগাযোগ তৈরি করা হচ্ছে 1
হ্যালো বব

নিস! ক্লায়েন্টটি সংগ্রহটি থেকে আইটেমটি "টান" দিলে কেবল প্রথম যোগাযোগ তৈরি হয়েছিল।


1
এই উত্তর আরও মনোযোগ প্রয়োজন! ধন্যবা
leon22

@ leon22 একেবারে +2
SNR

26

ধারণাটি বোঝার একটি সহজ উপায় এখানে: মৌলিক ধারণাটি হ'ল আপনি যদি এমন কোনও সংগ্রহ চান যা আপনি ব্যবহার করতে পারেন তবে " foreach" সংগ্রহটিতে আইটেমগুলি সংগ্রহ করা কোনও কারণে ব্যয়বহুল (যেমন একটি ডাটাবেস থেকে জিজ্ঞাসা করা), এবং আপনার প্রায়শই পুরো সংগ্রহের প্রয়োজন হবে না, তারপরে আপনি এমন একটি ফাংশন তৈরি করেন যা সংগ্রহের জন্য একবারে একটি আইটেম তৈরি করে এবং এটি গ্রাহকের কাছে ফেরত দেয় (তারপরে সংগ্রহের প্রচেষ্টাটি তাড়াতাড়ি শেষ করতে পারে)।

এটি এইভাবে ভাবুন: আপনি মাংসের কাউন্টারে যান এবং কাটা হ্যামের এক পাউন্ড কিনতে চান। কসাই একটি 10 ​​পাউন্ড হ্যামটি পিছনে নিয়ে যায়, স্লিকার মেশিনে রাখে, পুরো জিনিসটি টুকরো টুকরো করে ফেলে দেয়, তারপরে স্লাইসের গাদাটি আপনার কাছে ফিরিয়ে আনে এবং এর এক পাউন্ড বের করে দেয়। (পুরানো উপায়) সাথে yield, কসাই স্লিকার মেশিনকে কাউন্টারে নিয়ে আসে এবং প্রতিটি স্লাইস 1 পাউন্ড না হওয়া পর্যন্ত প্রতিটি স্লাইস কাটা এবং "ফলন" শুরু করে, তারপরে এটি আপনার জন্য জড়িয়ে দেয় এবং আপনার কাজ শেষ হয়ে যায়। কসাইয়ের জন্য ওল্ড ওয়ে আরও ভাল হতে পারে (তাকে তার পছন্দমতো তার মেশিনারি সাজিয়ে তুলতে দেয়) তবে গ্রাহকের পক্ষে বেশিরভাগ ক্ষেত্রে স্পষ্টতই নতুন উপায় আরও কার্যকর।


18

yieldশব্দ আপনি একটি তৈরি করার অনুমতি দেয় IEnumerable<T>একটি অন আকারে পুনরুক্তিকারীর ব্লক । এই পুনরুক্তিকারী ব্লকটি স্থগিত কার্যকরকরণকে সমর্থন করে এবং আপনি যদি ধারণার সাথে পরিচিত না হন তবে এটি প্রায় যাদুতে প্রদর্শিত হতে পারে। যাইহোক, দিনের শেষে এটি কেবল কোড যা কোনও অদ্ভুত কৌশল ছাড়াই কার্যকর করে।

একটি পুনরাবৃত্তকারী ব্লককে সিনট্যাকটিক চিনি হিসাবে বর্ণনা করা যেতে পারে যেখানে সংকলক একটি রাষ্ট্রীয় মেশিন তৈরি করে যা গণনার সংখ্যাটি কতদূর এগিয়ে গেছে তা ট্র্যাক করে। একটি গণনার গণনা করতে, আপনি প্রায়শই একটি foreachলুপ ব্যবহার করেন । তবে একটি foreachলুপ সিনট্যাকটিক চিনিও। সুতরাং আপনি দুটি বিমূর্ততা রিয়েল কোড থেকে সরিয়েছেন যার কারণে এটি প্রাথমিকভাবে বুঝতে পারে যে এটি কীভাবে সমস্ত একসাথে কাজ করে।

ধরে নিন যে আপনার খুব সাধারণ পুনরাবৃত্তকারী ব্লক রয়েছে:

IEnumerable<int> IteratorBlock()
{
    Console.WriteLine("Begin");
    yield return 1;
    Console.WriteLine("After 1");
    yield return 2;
    Console.WriteLine("After 2");
    yield return 42;
    Console.WriteLine("End");
}

রিয়েল ইটারেটর ব্লকগুলিতে প্রায়শই শর্ত এবং লুপ থাকে তবে আপনি যখন শর্তগুলি পরীক্ষা করেন এবং লুপগুলি আনرول করেন তখন তারা yieldঅন্য কোডের সাথে ইন্টারলিভ থাকা স্টেটমেন্ট হিসাবে শেষ হয় ।

foreachপুনরাবৃত্তকারী ব্লক গণনা করতে একটি লুপ ব্যবহৃত হয়:

foreach (var i in IteratorBlock())
    Console.WriteLine(i);

এখানে আউটপুট (এখানে কোনও আশ্চর্যের কিছু নেই):

শুরু করা
1
After এর পরে
2
2 পরে
42
শেষ

উপরে উল্লিখিত হিসাবে foreachসিনট্যাকটিক চিনি:

IEnumerator<int> enumerator = null;
try
{
    enumerator = IteratorBlock().GetEnumerator();
    while (enumerator.MoveNext())
    {
        var i = enumerator.Current;
        Console.WriteLine(i);
    }
}
finally
{
    enumerator?.Dispose();
}

এটি আনুষঙ্গিক করার প্রয়াসে আমি বিমূর্ততাগুলি সরানোর সাথে একটি ক্রম ডায়াগ্রাম আঁকিয়েছি:

সি # পুনরাবৃত্তকারী ব্লক সিকোয়েন্স চিত্র

সংকলক দ্বারা উত্পাদিত রাষ্ট্রযন্ত্রটিও গণকের প্রয়োগ করে তবে চিত্রটি আরও স্পষ্ট করতে আমি তাদের পৃথক দৃষ্টান্ত হিসাবে দেখিয়েছি। (যখন রাষ্ট্রীয় মেশিনটি অন্য থ্রেড থেকে অঙ্কিত হয় আপনি আসলে পৃথক দৃষ্টান্ত পান তবে সে বিবরণটি এখানে গুরুত্বপূর্ণ নয়))

প্রতিবার আপনি যখন আপনার পুনরাবৃত্তকারীকে ব্লক করেন তখন রাষ্ট্র মেশিনের একটি নতুন উদাহরণ তৈরি হয়। তবে, পুনরুক্তিকারী ব্লকের কোনও কোডই enumerator.MoveNext()প্রথমবার কার্যকর না হওয়া পর্যন্ত কার্যকর করা হয় না । এভাবেই স্থগিত কার্যকর করা কাজ করে। এখানে একটি (বরং নির্বোধ) উদাহরণ:

var evenNumbers = IteratorBlock().Where(i => i%2 == 0);

এই সময়ে পুনরুক্তি কার্যকর করা হয়নি। Whereদফা একটি নতুন সৃষ্টি IEnumerable<T>যে গোপন IEnumerable<T>দ্বারা ফিরে IteratorBlockকিন্তু এই গণনীয় এখনো গণিত করতে হবে। আপনি যখন foreachলুপটি কার্যকর করেন তখন এটি ঘটে :

foreach (var evenNumber in evenNumbers)
    Console.WriteLine(eventNumber);

যদি আপনি গণনার দ্বিগুণ হন তবে প্রতিবারের মতো রাষ্ট্র মেশিনের একটি নতুন উদাহরণ তৈরি হয় এবং আপনার পুনরাবৃত্তকারী ব্লক একই কোডটি দু'বার কার্যকর করবে।

লক্ষ করুন যে, LINQ পদ্ধতি পছন্দ ToList(), ToArray(), First(), Count()ইত্যাদির ব্যবহার করবে foreachলুপ গণনীয় গনা। উদাহরণস্বরূপ, ToList()গণনার সমস্ত উপাদান গণনা করা হবে এবং সেগুলি একটি তালিকায় সংরক্ষণ করবে। পুনরাবৃত্তির পুনরায় কার্যকরকরণ ব্যতীত গণনার সমস্ত উপাদান পাওয়ার জন্য আপনি এখন তালিকাটি অ্যাক্সেস করতে পারেন। সেখানে একটি ট্রেড বন্ধ CPU- র ব্যবহার গণনীয় একাধিক বার উপাদান উত্পাদন করতে এবং মেমরি যখন মত পদ্ধতি ব্যবহার করে তাদের একাধিক বার অ্যাক্সেস করতে শুমার উপাদান সংরক্ষণ করতে মধ্যে ToList()


18

যদি আমি এটি সঠিকভাবে বুঝতে পারি, তবে আমি এখানে ফাংশনটির সাথে ফলন সহ আইনিংরেবল বাস্তবায়ন কার্যকারিতার দৃষ্টিকোণ থেকে এই শব্দটি কী করব।

  • এখানে একটি।
  • আপনার আর দরকার পড়লে আবার ফোন করুন।
  • আমি আপনাকে ইতিমধ্যে যা দিয়েছি তা মনে রাখব।
  • আমি কেবল তখনই জানব যখন আপনি আবার কল করবেন তখন আমি আপনাকে অন্য কিছু দিতে পারি।

সহজ এবং উজ্জ্বল
হ্যারি

10

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

জাভাস্ক্রিপ্টে, একই ধারণাটিকে জেনারেটর বলা হয়।


এখনও সেরা ব্যাখ্যা। এগুলিও কি অজগর একই জেনারেটর?
পেট্রোসমি

7

এটি আপনার অবজেক্টের জন্য একটি অগণনীয় তৈরি করার খুব সহজ এবং সহজ উপায়। সংকলকটি এমন একটি শ্রেণি তৈরি করে যা আপনার পদ্ধতিটি মোড় করে এবং এটি প্রয়োগ করে, এই ক্ষেত্রে, অনুমিত << বিষয়> ob ফলন কীওয়ার্ড ব্যতীত, আপনাকে এমন একটি বস্তু তৈরি করতে হবে যা আইওনামেবল <অবজেক্ট> প্রয়োগ করে।


5

এটি প্রচুর পরিমাণে অনুক্রম তৈরি করছে। এটি যা করে তা হ'ল স্থানীয় আইয়নুমেবল সিকোয়েন্স তৈরি করা এবং এটি একটি পদ্ধতির ফলাফল হিসাবে ফিরে আসা


3

এই লিঙ্কটির একটি সহজ উদাহরণ রয়েছে

এমনকি সহজ উদাহরণ এখানে

public static IEnumerable<int> testYieldb()
{
    for(int i=0;i<3;i++) yield return 4;
}

লক্ষ্য করুন যে ফলন ফিরতি পদ্ধতি থেকে ফিরে আসবে না। আপনি এমনকি WriteLineপরে একটি লাগাতে পারেনyield return

উপরেরটি 4 ইনট 4,4,4,4 এর একটি সংখ্যাসূচক উত্পাদন করে

এখানে একটি সঙ্গে WriteLine। তালিকায় ৪ টি যুক্ত করবে, এবিসি মুদ্রণ করবে, তারপরে তালিকায় ৪ টি যুক্ত করবে, তারপরে পদ্ধতিটি সম্পূর্ণ করবে এবং সুতরাং পদ্ধতিটি থেকে সত্যই ফিরে আসবে (পদ্ধতিটি শেষ হয়ে গেলে, যেমনটি কোনও রিটার্ন ছাড়াই একটি পদ্ধতিতে ঘটবে)। তবে এটির একটি মান, এর একটি IEnumerableতালিকা থাকবে intযা এটি সমাপ্তির পরে ফিরে আসে।

public static IEnumerable<int> testYieldb()
{
    yield return 4;
    console.WriteLine("abc");
    yield return 4;
}

এছাড়াও খেয়াল করুন যে আপনি যখন ফলন ব্যবহার করবেন তখন আপনি যা ফিরিয়ে দিচ্ছেন তা ফাংশনের মতো একই ধরণের নয়। এটি IEnumerableতালিকার মধ্যে একটি উপাদানের ধরণের ।

আপনি পদ্ধতির রিটার্ন টাইপ হিসাবে ফলন ব্যবহার করুন IEnumerable। পদ্ধতি এর রিটার্ন টাইপ হয় তাহলে intবা List<int>আপনার ব্যবহৃত ওয়েবসাইট ও yield, তাহলে এটি কম্পাইল করা হবে না। আপনি IEnumerableফলন ছাড়াই IEnumerableপদ্ধতি রিটার্নের ধরণটি ব্যবহার করতে পারেন তবে মনে হয় আপনি পদ্ধতিটি রিটার্নের ধরণ ছাড়াই ফলন ব্যবহার করতে পারবেন না ।

এবং এটি কার্যকর করার জন্য আপনাকে এটিকে একটি বিশেষ উপায়ে কল করতে হবে।

static void Main(string[] args)
{
    testA();
    Console.Write("try again. the above won't execute any of the function!\n");

    foreach (var x in testA()) { }


    Console.ReadLine();
}



// static List<int> testA()
static IEnumerable<int> testA()
{
    Console.WriteLine("asdfa");
    yield return 1;
    Console.WriteLine("asdf");
}

দ্রষ্টব্য- যদি সিলেকম্যানিকে বোঝার চেষ্টা করা হয় তবে এটি উত্পাদন এবং জেনেরিকগুলিও ব্যবহার করে .. এই উদাহরণটি সাহায্য করতে পারে public static IEnumerable<TResult> testYieldc<TResult>(TResult t) { yield return t; }এবং public static IEnumerable<TResult> testYieldc<TResult>(TResult t) { return new List<TResult>(); }
বার্লপ

দেখতে খুব ভালো ব্যাখ্যার মতো! এটি গ্রহণযোগ্য উত্তর হতে পারে।
পঙ্গাপুণ্ডিত

@ পঙ্গাপুণ্ডিত ধন্যবাদ, আমার উত্তর অবশ্যই স্পষ্ট এবং সহজ, তবে আমি নিজে থেকে ফলন বেশি ব্যবহার করিনি, অন্যান্য উত্তরদাতাদের কাছে এর চেয়ে অনেক বেশি অভিজ্ঞতা এবং এর ব্যবহার সম্পর্কে আমার জ্ঞান রয়েছে। আমি এখানে ফলন সম্পর্কে যা লিখেছিলাম তা সম্ভবত আমার মাথাটি স্ক্র্যাচ করে কিছু উত্তরগুলি এখানে এবং সেই ডটনেটার্পলসের লিঙ্কে বের করার চেষ্টা করে! তবে যেহেতু আমি yield returnএটি ভালভাবে জানি না (আমি উল্লেখ করা সহজ জিনিস ব্যতীত), এবং এটি বেশি ব্যবহার করি নি এবং এর ব্যবহারগুলি খুব বেশি জানি না, তাই আমি মনে করি এটি গ্রহণযোগ্য হওয়া উচিত।
বারলপ

3

ফলন কীওয়ার্ড সম্পর্কে একটি প্রধান পয়েন্ট হ'ল আলজি এক্সিকিউশন । এখন আমি অলস এক্সিকিউশন বলতে যা বোঝাতে চাইছি তা প্রয়োজনে কার্যকর করা। এটি দেওয়ার আরও ভাল উপায় হ'ল একটি উদাহরণ দিয়ে

উদাহরণ: ফলন ব্যবহার না করা অর্থাৎ কোনও অলস কার্যকারিতা নয়।

        public static IEnumerable<int> CreateCollectionWithList()
        {
            var list =  new List<int>();
            list.Add(10);
            list.Add(0);
            list.Add(1);
            list.Add(2);
            list.Add(20);

            return list;
        }

উদাহরণ: ফলন অর্থাৎ অলস কার্যকারিতা ব্যবহার করা।

    public static IEnumerable<int> CreateCollectionWithYield()
    {
        yield return 10;
        for (int i = 0; i < 3; i++) 
        {
            yield return i;
        }

        yield return 20;
    }

এখন যখন আমি উভয় পদ্ধতি কল।

var listItems = CreateCollectionWithList();
var yieldedItems = CreateCollectionWithYield();

আপনি তালিকা লক্ষ্য করবেন আইটেমগুলির মধ্যে একটি 5 টি আইটেম থাকবে (ডিবাগ করার সময় তালিকার আইটেমগুলিতে আপনার মাউসটিকে ঘোরান)। ফলন আইটেমগুলিতে আইটেমগুলিতে নয় কেবল পদ্ধতিটির একটি রেফারেন্স থাকবে। এর অর্থ এটি পদ্ধতির অভ্যন্তরে আইটেমগুলি পাওয়ার প্রক্রিয়াটি কার্যকর করেনি। যখন প্রয়োজন হয় তখন ডেটা পাওয়ার একটি অত্যন্ত দক্ষ উপায়। ওরিএম-এ যেমন সত্তা ফ্রেমওয়ার্ক এবং এনএইচবারনেট ইত্যাদির মধ্যে ফলনের আসল বাস্তবায়ন দেখা যায় yield


-3

এটি কিছু রুবি সদ্ব্যবহার আনার চেষ্টা করছে :)
ধারণা: এটি কিছু নমুনা রুবি কোড যা অ্যারের প্রতিটি উপাদান প্রিন্ট করে

 rubyArray = [1,2,3,4,5,6,7,8,9,10]
    rubyArray.each{|x| 
        puts x   # do whatever with x
    }

অ্যারের প্রতিটি পদ্ধতি বাস্তবায়নের জন্য অ্যারের প্রতিটি উপাদান পরিষ্কারভাবে এক্স হিসাবে উপস্থাপিত কলারের কাছে নিয়ন্ত্রণের ফল দেয় ('x রাখে x') । কলকারী x এর সাথে যা করার দরকার তা করতে পারে।

যাইহোক। নেট এখানে পুরোপুরি যায় না .. সি # এর মনে হয় যে ফলন আইনিউমারেবলের সাথে একত্রে হয়েছে, মেন্ডেল্টের প্রতিক্রিয়াতে যেমন দেখানো হয়েছে তেমনভাবে আপনাকে কলারে একটি ফোরচ লুপ লিখতে বাধ্য করছেন। সামান্য কম মার্জিত।

//calling code
foreach(int i in obCustomClass.Each())
{
    Console.WriteLine(i.ToString());
}

// CustomClass implementation
private int[] data = {1,2,3,4,5,6,7,8,9,10};
public IEnumerable<int> Each()
{
   for(int iLooper=0; iLooper<data.Length; ++iLooper)
        yield return data[iLooper]; 
}

7
-1 এই উত্তরটি আমার কাছে ঠিক শোনা যাচ্ছে না। হ্যাঁ, সি # এর yieldসাথে মিলিত হয়েছে IEnumerable, এবং সি # তে একটি "ব্লক" এর রুবি ধারণা নেই। তবে সি # তে ল্যাম্বডাস রয়েছে, যা কোনও ForEachপদ্ধতি বাস্তবায়নের সুযোগ দিতে পারে , অনেকটা রুবির মতোই eachএটির অর্থ এই নয় যে এটি করা ভাল ধারণা হবে
আরএসেন্না

আরও ভাল: সর্বজনীন আইয়ুনামেবল <মিন্ট> প্রতিটি () {ইনড ইনডেক্স = 0; ফলন ফেরতের ডেটা [সূচক ++]; }
আতা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.