سؤال

ما زلت لا أفهم تمامًا ما أ إنهاء هل قمت بنشر هذين المثالين وأريد أن أعرف ما إذا كانت هذه الأمثلة عبارة عن إغلاق أم لا؟

المثال أ:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

Action<string> FilterSubFoldersStartA =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith("A")));

FilterSubFoldersStartA(@"c:\tempa");
FilterSubFoldersStartA(@"c:\tempb");

المثال ب:

List<DirectoryInfo> subFolders = new List<DirectoryInfo>();

string filter = "A";

Action<string> FilterSubFoldersStartGen =
  s => subFolders.
       AddRange((new DirectoryInfo(s)).GetDirectories().
       Where(d => d.Name.StartsWith(filter)));

FilterSubFoldersStartGen(@"c:\tempa");

filter = "B"; 

FilterSubFoldersStartGen(@"c:\tempb");
هل كانت مفيدة؟

المحلول

نعم، الإغلاق ليس أكثر من وظيفة "تحفظ" بعض المتغيرات من البيئة التي تم تعريفها فيها.لذا، في كلا المثالين، يقوم الإجراء المحدد بحفظ القائمة المسماة subFolders, ، والتي يمكن الرجوع إليها بواسطة الوظائف حتى بعد أن يكون المتغير المحلي خارج النطاق.ال filter يتم أيضًا حفظ المتغير في المثال الثاني بواسطة الوظيفة المحددة.

تعريف أكثر دقة هنا

نصائح أخرى

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

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

ولكن ما نعنيه عادة عندما نتحدث عن "استخدام عمليات الإغلاق" هو ​​أن تعبيرات لامدا يمكنها استخدام جميع المتغيرات المحلية المرئية في المكان الذي تم الإعلان عنه.كلهم جزء من إغلاقه.

في حالتك، d هي ببساطة معلمة دالة lambda، وبما أن هذا هو كل ما تستخدمه في الحالة الأولى، فأنت لا تستفيد حقًا من عمليات الإغلاق.

وفي الحالة الثانية، filter لم يتم تعريفه في تعبير لامدا، فهو ليس معلمة أو أي شيء.إنه متغير محلي والذي يحدث أن يكون مرئيًا في المكان الذي تم فيه إعلان لامدا.لذلك فهو جزء من إغلاق لامدا، والذي يسمح لك بالإشارة إليه في نص لامدا.

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

كلا المثالين لهما عمليات إغلاق.في الطريقة "أ" المجهولة، تلتقط المجلدات الفرعية المتغيرة المحلية.في الطريقة "B" المجهولة، يتم التقاط المتغيرات المحلية والمجلدات الفرعية والتصفية.ألقِ نظرة أيضًا هنا.

ملاحظة. لاحظ أيضًا أنك تستخدم بالفعل الإغلاق في "A" لأنك تستخدم متغير المجلدات الفرعية.

هنا مثال من http://www.agileatwork.com/a-proper-closure-in-csharp/ لشيء قد يبدو مألوفًا أكثر إذا كنت مرتاحًا مع JavaScript.يتم إنشاء إغلاق حول tax متغير بحيث يتم الحساب مرة واحدة فقط.إنه ليس بالأمر السهل تمامًا على العين، ولكن من الرائع أنه يمكنك القيام بهذا النوع من الأشياء في لغة C#.

public class Order
{
    public Order(ITaxCalculator taxCalculator)
    {
        CalculateTax = new Func<Func<decimal>>(() =>
        {
            decimal? tax = null;
            return () =>
            {
                if (!tax.HasValue)
                {
                    tax = taxCalculator.Calculate(this);
                }
                return tax.Value;
            };
        })();
    }

    public Func<decimal> CalculateTax { get; set; }

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