ما هي تطبيقات الحياة الحقيقية للمحصول؟

StackOverflow https://stackoverflow.com/questions/17125

  •  08-06-2019
  •  | 
  •  

سؤال

انا اعرف ماذا yield نعم، ولقد رأيت بعض الأمثلة، ولكن لا أستطيع التفكير في تطبيقات الحياة الواقعية، هل استخدمتها لحل مشكلة معينة؟

(من الناحية المثالية بعض المشاكل التي لا يمكن حلها بطريقة أخرى)

هل كانت مفيدة؟

المحلول

أدرك أن هذا سؤال قديم (ما قبل جون سكيت؟) لكنني كنت أفكر في هذا السؤال بنفسي مؤخرًا.لسوء الحظ فإن الإجابات الحالية هنا (في رأيي) لا تذكر الميزة الأكثر وضوحًا لبيان العائد.

أكبر فائدة لبيان العائد هو أنه يسمح لك بالتكرار على قوائم كبيرة جدًا مع استخدام أكثر كفاءة للذاكرة ثم استخدام قائمة قياسية على سبيل المثال.

على سبيل المثال، لنفترض أن لديك استعلام قاعدة بيانات يُرجع مليون صف.يمكنك استرداد كافة الصفوف باستخدام DataReader وتخزينها في قائمة، وبالتالي تتطلب list_size * Row_size بايت من الذاكرة.

أو يمكنك استخدام بيان العائد لإنشاء مكرر وتخزين صف واحد فقط في الذاكرة في كل مرة.في الواقع، يمنحك هذا القدرة على توفير إمكانية "التدفق" عبر مجموعات كبيرة من البيانات.

علاوة على ذلك، في الكود الذي يستخدم التكرار، يمكنك استخدام حلقة foreach بسيطة ويمكنك أن تقرر الخروج من الحلقة كما هو مطلوب.إذا قمت بالانقطاع مبكرًا، فلن تضطر إلى استرداد مجموعة البيانات بأكملها عندما تحتاج فقط إلى الصفوف الخمسة الأولى (على سبيل المثال).

متعلق:

Ideally some problem that cannot be solved some other way

لا يمنحك بيان العائد أي شيء لا يمكنك القيام به باستخدام تطبيق التكرار المخصص الخاص بك، ولكنه يوفر عليك الحاجة إلى كتابة التعليمات البرمجية المعقدة المطلوبة في كثير من الأحيان.هناك عدد قليل جدًا من المشكلات (إن وجدت) التي لا يمكن حلها بأكثر من طريقة واحدة.

فيما يلي بعض الأسئلة والأجوبة الحديثة التي توفر مزيدًا من التفاصيل:

قيمة الكلمة الرئيسية العائد المضافة؟

هل العائد مفيد خارج LINQ؟

نصائح أخرى

في الواقع أستخدمه بطريقة غير تقليدية على موقعي IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

لذا فهو يتحقق بشكل أساسي مما إذا كان عرض الفكرة مسموحًا به حاليًا وما إذا كان كذلك فإنه يعيد الفكرة.إذا لم يكن الأمر كذلك، فسيتم تخطيه فقط.يتيح لي هذا تخزين الأفكار مؤقتًا مع الاستمرار في عرض الأفكار للمستخدمين المصرح لهم.وإلا فسيتعين علي إعادة سحبها في كل مرة بناءً على الأذونات، حيث يتم إعادة ترتيبها كل ساعة فقط.

أحد الاستخدامات المثيرة للاهتمام هو استخدامها كآلية للبرمجة غير المتزامنة خاصة للمهام التي تستغرق خطوات متعددة وتتطلب نفس مجموعة البيانات في كل خطوة.مثالان على ذلك هما Jeffery Richters AysncEnumerator الجزء 1 و الجزء 2.يستخدم وقت تشغيل التزامن والتنسيق (CCR) أيضًا هذه التقنية مكررات CCR.

يتم تنفيذ عوامل تشغيل LINQ في الفئة Enumerable كمكررات يتم إنشاؤها باستخدام بيان العائد.فهو يسمح لك بتسلسل العمليات مثل Select() و Where() دون تعداد أي شيء فعليًا حتى تستخدم العداد فعليًا في حلقة، عادةً باستخدام com.foreach إفادة.بالإضافة إلى ذلك، نظرًا لأنه يتم حساب قيمة واحدة فقط عند استدعاء IEnumerator.MoveNext() إذا قررت إيقاف التجميع الأوسط، فسوف تقوم بحفظ نتيجة الأداء لحساب كافة النتائج.

يمكن أيضًا استخدام التكرارات لتنفيذ أنواع أخرى من التقييم البطيء حيث يتم تقييم التعبيرات فقط عندما تحتاج إليها.تستطيع ايضا استخذام أَثْمَر لمزيد من الأشياء الفاخرة مثل coroutines.

الاستخدام الجيد الآخر للمحصول هو تنفيذ دالة على عناصر IEnumerable وإرجاع نتيجة من نوع مختلف، على سبيل المثال:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}

يمكن أن يؤدي استخدام العائد إلى منع الانحدار إلى نوع ملموس.يعد هذا مفيدًا لضمان عدم تلاعب مستهلك المجموعة بها.

تستطيع ايضا استخذام yield return للتعامل مع سلسلة من نتائج الوظائف كقائمة.على سبيل المثال، لنأخذ في الاعتبار شركة تدفع رواتب موظفيها كل أسبوعين.يمكن للمرء استرداد مجموعة فرعية من تواريخ الرواتب كقائمة باستخدام هذا الرمز:

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top