سؤال

string [] files = new string[2];
files[0] = "ThinkFarAhead.Example.Settings.Configuration_Local.xml";
files[1] = "ThinkFarAhead.Example.Settings.Configuration_Global.xml";

//Resharper complains this is an "access to modified closure"
for (int i = 0; i < files.Length; i++ )
{
    // Resharper disable AccessToModifiedClosure
    if(Array.Exists(Assembly.GetExecutingAssembly().GetManifestResourceNames(),
    delegate(string name) { return name.Equals(files[i]); }))
         return Assembly.GetExecutingAssembly().GetManifestResourceStream(files[i]);
    // ReSharper restore AccessToModifiedClosure
}

يبدو أن ما ورد أعلاه يعمل بشكل جيد على الرغم من أن ReSharper يشكو من أن هذا هو "الوصول إلى الإغلاق المعدل".هل يمكن لأحد أن يلقي الضوء على هذا؟

(تابع هذا الموضوع هنا)

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

المحلول

في هذه الحالة، أنها بخير، منذ كنت في الواقع تنفيذ مندوب <م> في الحلقة.

إذا تم توفير مندوب واستخدامه في وقت لاحق، ومع ذلك، كنت تجد أن كل من المندوبين أن رمي الاستثناءات عند محاولة الوصول إلى الملفات [أنا] - انهم التقاط <م> متغير i بدلا من قيمته في وقت إنشاء المندوبين.

وباختصار، انه شيء أن تكون على علم بأنه <م> إمكانات فخ، ولكن في هذه الحالة فإنه لا يضر بك.

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

نصائح أخرى

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

private sealed class Closure
{
    public string[] files;
    public int i;

    public bool YourAnonymousMethod(string name)
    {
        return name.Equals(this.files[this.i]);
    }
}

وكما ذكر أعلاه، وتعمل وظيفة لأنه يتم استدعاء المسندات مباشرة بعد إنشاء. فإن المترجم تولد شيئا مثل:

private string Works()
{
    var closure = new Closure();

    closure.files = new string[3];
    closure.files[0] = "notfoo";
    closure.files[1] = "bar";
    closure.files[2] = "notbaz";

    var arrayToSearch = new string[] { "foo", "bar", "baz" };

    //this works, because the predicates are being executed during the loop
    for (closure.i = 0; closure.i < closure.files.Length; closure.i++)
    {
        if (Array.Exists(arrayToSearch, closure.YourAnonymousMethod))
            return closure.files[closure.i];
    }

    return null;
}

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

"الملفات" هي أ المتغير الخارجي الملتقط لأنه تم التقاطها بواسطة وظيفة المفوض المجهول.يتم تمديد عمره بواسطة وظيفة المفوض المجهول.

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

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specation/expressions#outer-variables

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

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