في C#, لماذا لا مجهول تحتوي على طريقة العائد البيان ؟

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

سؤال

اعتقدت أنه سيكون من الجميل أن تفعل شيئا من هذا القبيل (مع امدا القيام العائد العودة):

public IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new()
{
    IList<T> list = GetList<T>();
    var fun = expression.Compile();

    var items = () => {
        foreach (var item in list)
            if (fun.Invoke(item))
                yield return item; // This is not allowed by C#
    }

    return items.ToList();
}

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

لأنه لم يكن يسمح فقط إنشاء قائمة إضافة العناصر إلى ذلك.

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

المحلول

إريك ليبرت كتب مؤخرا سلسلة من بلوق وظيفة حول لماذا العائد لا يسمح في بعض الحالات.

EDIT2:

  • الجزء 7 (هذه واحدة نشرت في وقت لاحق وتحديدا عناوين هذا السؤال)

ربما ستجد الجواب هناك...


EDIT1:هذا هو موضح في التعليقات من 5 جزء في إيريك جواب السيد أبهيجيت باتل التعليق:

Q :

إيريك ،

يمكنك أيضا توفر بعض التبصر لماذا "ينتج" لا يسمح داخل مجهول الأسلوب أو التعبير امدا

A :

سؤال جيد.أنا أحب أن يكون مجهول مكرر كتل.سيكون رائع أن تكون قادرة على بناء نفسك قليلا تسلسل مولد في مكان مغلق المحلية المتغيرات.السبب ليس هو واضحة:فوائد لا تفوق التكاليف.الذهول من مما يجعل تسلسل المولدات في المكان في الواقع صغيرة جدا في جراند مخطط الأشياء الاسمية طرق القيام بهذه المهمة بشكل جيد بما فيه الكفاية في معظم السيناريوهات.لذا فوائد لا التي مقنعة.

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

كما مكرر كتل أبدا "عش" ، على عكس طرق مجهولة.مكرر مصحح يمكن أن نفترض أن جميع مكرر كتل "أعلى مستوى".

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

نصائح أخرى

إريك ليبرت كتب ممتازة سلسلة من المقالات حول القيود (و قرارات التصميم التأثير على هذه الاختيارات) على مكرر كتل

ولا سيما مكرر كتل يتم تنفيذها من قبل بعض متطورة مترجم رمز التحولات.هذه التحولات سيكون لها أثر مع التحولات التي تحدث داخل وظائف مجهولة أو lambdas مثل ذلك في ظروف معينة فإنها على حد سواء في محاولة تحويل الكود إلى أخرى بناء يتنافى مع الآخر.

ونتيجة لذلك فهي ممنوعة من التفاعل.

كيف مكرر كتل العمل تحت غطاء محرك السيارة هو التعامل مع هنا.

كمثال بسيط من عدم التوافق:

public IList<T> GreaterThan<T>(T t)
{
    IList<T> list = GetList<T>();
    var items = () => {
        foreach (var item in list)
            if (fun.Invoke(item))
                yield return item; // This is not allowed by C#
    }

    return items.ToList();
}

مترجم في نفس الوقت الرغبة في تحويل هذا إلى شيء من هذا القبيل:

// inner class
private class Magic
{
    private T t;
    private IList<T> list;
    private Magic(List<T> list, T t) { this.list = list; this.t = t;}

    public IEnumerable<T> DoIt()
    {
        var items = () => {
            foreach (var item in list)
                if (fun.Invoke(item))
                    yield return item;
        }
    }
}

public IList<T> GreaterThan<T>(T t)
{
    var magic = new Magic(GetList<T>(), t)
    var items = magic.DoIt();
    return items.ToList();
}

و في نفس الوقت مكرر الجانب هو محاولة للقيام بذلك العمل لجعل القليل من آلة الدولة.بعض الأمثلة البسيطة قد عمل مع قدرا كبيرا من التعقل التدقيق (أولا التعامل مع (ربما تعسفا) متداخلة إغلاق) ثم رؤية ما إذا كان أسفل مستوى الناتج الطبقات يمكن أن تتحول إلى التكرار أجهزة الدولة.

ولكن هذا لن يكون

  1. الكثير جدا من العمل.
  2. لا يمكن العمل في جميع الحالات دون على الأقل مكرر كتلة جانب كونها قادرة على منع إغلاق جانب من تطبيق بعض التحولات في الكفاءة (مثل تعزيز المتغيرات المحلية إلى المتغيرات سبيل المثال بدلا من كاملة إغلاق الدرجة).
    • إذا كان هناك حتى فرصة ضئيلة من التداخل حيث كان من المستحيل أو من الصعب بما فيه الكفاية لا يمكن تنفيذها ثم عدد من دعم القضايا الناتجة من المرجح أن تكون عالية منذ الدقيقة كسر التغيير سوف تضيع على العديد من المستخدمين.
  3. يمكن أن يكون بسهولة جدا عملت حولها.

في المثال الخاص بك مثل ذلك:

public IList<T> Find<T>(Expression<Func<T, bool>> expression) 
    where T : class, new()
{
    return FindInner(expression).ToList();
}

private IEnumerable<T> FindInner<T>(Expression<Func<T, bool>> expression) 
    where T : class, new()
{
    IList<T> list = GetList<T>();
    var fun = expression.Compile();
    foreach (var item in list)
        if (fun.Invoke(item))
            yield return item;
}

للأسف أنا لا أعرف لماذا لم يسمحوا هذا، منذ وبطبيعة الحال فإنه من الممكن تماما أن تفعل نتصور كيف ستعمل.

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

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

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

لسؤال دقيق 100٪ أود أن أقترح عليك استخدام موقع Microsoft الاتصال و الإبلاغ عن السؤال، أنا متأكد من أنك سوف تحصل على شيء صالحة للاستعمال في المقابل.

وأود أن تفعل هذا:

IList<T> list = GetList<T>();
var fun = expression.Compile();

return list.Where(item => fun.Invoke(item)).ToList();

وبطبيعة الحال كنت في حاجة إلى System.Core.dll المشار إليه من .NET Framework 3.5 لأسلوب ينق. وتشمل:

using System.Linq;

وابتهاج،

وماكر

وربما لمجرد وجود قيود على بناء الجملة. في Visual Basic .NET، التي هي مشابهة جدا لC #، فمن الممكن تماما في حين محرجا لكتابة

Sub Main()
    Console.Write("x: ")
    Dim x = CInt(Console.ReadLine())
    For Each elem In Iterator Function()
                         Dim i = x
                         Do
                             Yield i
                             i += 1
                             x -= 1
                         Loop Until i = x + 20
                     End Function()
        Console.WriteLine($"{elem} to {x}")
    Next
    Console.ReadKey()
End Sub

لاحظ أيضا ' here قوسين. وظيفة امدا Iterator Function ... End Function <م> عودة وIEnumerable(Of Integer) لكن لا مثل هذا الكائن نفسه. يجب أن يطلق عليه للحصول على هذا الكائن.

والتعليمات البرمجية المحولة من قبل [1] يثير أخطاء في C # 7.3 (CS0149):

static void Main()
{
    Console.Write("x: ");
    var x = System.Convert.ToInt32(Console.ReadLine());
    // ERROR: CS0149 - Method name expected 
    foreach (var elem in () =>
    {
        var i = x;
        do
        {
            yield return i;
            i += 1;
            x -= 1;
        }
        while (!i == x + 20);
    }())
        Console.WriteLine($"{elem} to {x}");
    Console.ReadKey();
}

وأنا لا أوافق بشدة للسبب الوارد في إجابات أخرى أنه من الصعب على المترجم في التعامل معها. يتم إنشاء Iterator Function() ترى في المثال VB.NET خصيصا لالمكررات امدا.

في VB، هناك الكلمة Iterator. انه ليس لديها C # نظيره. IMHO، لا يوجد سبب حقيقي هذه ليست سمة من سمات C #.

وحتى إذا كنت حقا، حقا نريد وظائف مكرر غير معروفة وتستخدم حاليا Visual Basic أو (أنا لم تأكدت منه) F #، كما جاء في تعليق <لأ href = "https://blogs.msdn.microsoft. كوم / ericlippert / 2009/08/24 / مكرر-بنات-جزء من سبعة لماذا-لا-مجهول-المكررات / "يختلط =" نوفولو noreferrer "> الجزء رقم 7 رداThomas يفيسك (لا السيطرة + F لF #).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top