পরিবর্তিত বন্ধের অ্যাক্সেস (2)


101

এটি অ্যাক্সেস থেকে পরিবর্তিত সমাপ্তিতে প্রশ্নের বর্ধিতাংশ । নিম্নলিখিতগুলি উত্পাদন ব্যবহারের জন্য যথেষ্ট নিরাপদ কিনা তা আমি কেবল যাচাই করতে চাই।

List<string> lists = new List<string>();
//Code to retrieve lists from DB    
foreach (string list in lists)
{
    Button btn = new Button();
    btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}

আমি কেবল একবার স্টার্টআপের পরে উপরের মাধ্যমে চলি। আপাতত এটি ঠিকঠাক কাজ করছে বলে মনে হচ্ছে। জোন যেমন কিছু ক্ষেত্রে পাল্টা ফলাফল সম্পর্কে উল্লেখ করেছেন। তাহলে এখানে আমার কী দেখার দরকার? তালিকাটি যদি একাধিকবার চালানো হয় তবে তা ঠিক হবে?


18
অভিনন্দন, আপনি এখন পুনঃভাগের ডকুমেন্টেশনের অংশ। সঙ্গম.জেটব্রেইনস.এন.
ডিসপ্লের

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

উত্তর:


159

সি # 5 এর পূর্বে আপনাকে পূর্বাভাসের অভ্যন্তরে একটি পরিবর্তনশীল পুনরায় ঘোষণা করতে হবে - অন্যথায় এটি ভাগ করা হয়, এবং আপনার সমস্ত হ্যান্ডলারগুলি শেষ স্ট্রিংটি ব্যবহার করবে:

foreach (string list in lists)
{
    string tmp = list;
    Button btn = new Button();
    btn.Click += new EventHandler(delegate { MessageBox.Show(tmp); });
}

তাৎপর্যপূর্ণভাবে, নোট করুন যে সি # 5 থেকে, এটি পরিবর্তিত হয়েছে এবং বিশেষত এর ক্ষেত্রেforeach আপনার আর এটি করার দরকার নেই: প্রশ্নের কোডটি প্রত্যাশার মতো কাজ করবে।

এটি এই পরিবর্তন ব্যতীত কাজ না করার জন্য, নিম্নলিখিতটি বিবেচনা করুন:

string[] names = { "Fred", "Barney", "Betty", "Wilma" };
using (Form form = new Form())
{
    foreach (string name in names)
    {
        Button btn = new Button();
        btn.Text = name;
        btn.Click += delegate
        {
            MessageBox.Show(form, name);
        };
        btn.Dock = DockStyle.Top;
        form.Controls.Add(btn);
    }
    Application.Run(form);
}

উপরের সি # 5 এর আগে চালান , এবং প্রতিটি বোতাম একটি আলাদা নাম দেখায়, বোতামগুলি ক্লিক করে "উইলমা" চারবার দেখায়।

এটি কারণ ভাষার স্পেস (ECMA 334 v4, 15.8.4) (সি # 5 এর আগে) সংজ্ঞায়িত করেছে:

foreach (V v in x) embedded-statement এরপরে প্রসারিত:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
         while (e.MoveNext()) {
            v = (V)(T)e.Current;
             embedded-statement
        }
    }
    finally {
         // Dispose e
    }
}

নোট করুন যে ভেরিয়েবলটি v(যা আপনার list) লুপের বাইরে ঘোষিত হয় । সুতরাং ক্যাপচারড ভেরিয়েবলের নিয়ম অনুসারে তালিকার সমস্ত পুনরাবৃত্তি ক্যাপচারড ভেরিয়েবল ধারককে ভাগ করে দেবে।

সি # 5 এর পরে, এটি পরিবর্তন করা হয়েছে: পুনরাবৃত্তির পরিবর্তনশীল ( v) লুপের অভ্যন্তরে স্কুপ করা হবে । আমার কাছে কোনও স্পেসিফিকেশন রেফারেন্স নেই তবে এটি মূলত:

{
    E e = ((C)(x)).GetEnumerator();
    try {
        while (e.MoveNext()) {
            V v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
         // Dispose e
    }
}

আবার সদস্যতা বাতিল; আপনি যদি সক্রিয়ভাবে কোনও বেনামী হ্যান্ডলারটি সাবস্ক্রাইব করতে চান তবে কৌশলটি হ্যান্ডলারটি নিজেই ক্যাপচার করা হবে:

EventHandler foo = delegate {...code...};
obj.SomeEvent += foo;
...
obj.SomeEvent -= foo;

তেমনি, আপনি যদি একবারের ইভেন্ট ইভেন্ট হ্যান্ডলার চান (যেমন লোড ইত্যাদি):

EventHandler bar = null; // necessary for "definite assignment"
bar = delegate {
  // ... code
  obj.SomeEvent -= bar;
};
obj.SomeEvent += bar;

এটি এখন স্ব-সদস্যতা ছাড়াই ;- পি


যদি এটি হয় তবে ডেলিগেটের পরিবেশন হিসাবে অ্যাপটি বন্ধ না হওয়া পর্যন্ত অস্থায়ী পরিবর্তনশীল মেমরিতে থাকবে এবং ভেরিয়েবলটি প্রচুর স্মৃতি গ্রহণ করলে খুব বিশাল লুপের জন্য এটি করা ঠিক হবে না। আমি কি সঠিক?
ত্রুটিপূর্ণ

1
এটি সময়ের সাথে স্মৃতিতে থাকবে যে ইভেন্টের সাথে জিনিসগুলি (বোতাম) রয়েছে। একবারে কেবলমাত্র প্রতিনিধিদের সদস্যতার জন্য সাবস্ক্রাইব করার একটি উপায় আছে যা আমি পোস্টটিতে যুক্ত করব।
মার্ক গ্র্যাভেল

2
তবে আপনার বক্তব্যকে যোগ্য করে তোলার জন্য: হ্যাঁ, ক্যাপচারড ভেরিয়েবলগুলি আসলে একটি ভেরিয়েবলের পরিধি বাড়াতে পারে। আপনি প্রত্যাশিত জিনিসগুলি ক্যাপচার না করার জন্য আপনাকে সতর্কতা অবলম্বন করা উচিত ...
মার্ক গ্রাভেল

1
আপনি দয়া করে আপনার উত্তরটি সি # 5.0 টিপিতে পরিবর্তনের ক্ষেত্রে আপডেট করতে পারবেন? কেবল এটি সি # তে পূর্বাভাস লুপ সম্পর্কিত একটি দুর্দান্ত উইকি ডকুমেন্টেশন তৈরি করতে। ফোরচ লুপ বিট.ly / WzBV3L এর চিকিত্সা করে সি # 5.0 সংকলক পরিবর্তনের বিষয়ে ইতিমধ্যে কিছু ভাল উত্তর রয়েছে তবে সেগুলি উইকির মতো সংস্থান নয়।
ইলিয়া ইভানভ

1
@ কোস হ্যাঁ, for5.0
মার্ক গ্রাভেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.