কেন এই কোডটি 'সংগ্রহটি সংশোধন করা হয়েছিল', কিন্তু যখন আমি এর আগে কিছু পুনরুক্তি করি তখন তা হয় না?


102
var ints = new List< int >( new[ ] {
    1,
    2,
    3,
    4,
    5
} );
var first = true;
foreach( var v in ints ) {
    if ( first ) {
        for ( long i = 0 ; i < int.MaxValue ; ++i ) { //<-- The thing I iterate
            ints.Add( 1 );
            ints.RemoveAt( ints.Count - 1 );
        }
        ints.Add( 6 );
        ints.Add( 7 );
    }
    Console.WriteLine( v );
    first = false;
}

আপনি যদি ভিতরের forলুপটি মন্তব্য করেন তবে তা ছোঁড়ে, এটি সম্ভবত কারণ আমরা সংগ্রহটিতে পরিবর্তন করেছি।

এখন আপনি যদি এটি আপত্তিহীন করেন তবে কেন এই লুপটি আমাদের সেই দুটি আইটেম যুক্ত করার অনুমতি দেয়? এটি আধ মিনিটের মতো চালানোর জন্য কিছুটা সময় নেয় (পেন্টিয়াম সিপিইউতে), তবে এটি ছুঁড়ে না, এবং মজার বিষয়টি এটি আউটপুট করে:

ভাবমূর্তি

এটি কিছুটা প্রত্যাশিত ছিল, তবে এটি ইঙ্গিত করে যে আমরা পরিবর্তন করতে পারি এবং এটি আসলে সংগ্রহকে পরিবর্তন করে। কোন ধারণা কেন এই আচরণ ঘটছে?


2
ইহা আকর্ষণীয়. আমি আচরণটি পুনরুত্পাদন করতে পারতাম, তবে আমি যদি ইন্টার.ম্যাক্সভ্যালু থেকে অভ্যন্তরীণ লুপটি 100 এর মতো মানতে পরিবর্তন করি তবে
স্টিভ

আপনি কতক্ষণ অপেক্ষা করেছেন? int.MaxValueপুনরাবৃত্তিগুলি শেষ করতে বেশ খানিকটা সময় সময় লাগে ...
জন স্কিটি

1
আমি বিশ্বাস করি যে ফোরচ পরীক্ষা প্রতিটি লুপের শুরুতে সংশোধন করা হয়েছে কিনা তা যাচাই করে দেখুন .... সুতরাং প্রতিটি লুপের মধ্যে আইটেমটি যুক্ত করে মুছে ফেলা কোনও ত্রুটি ছুঁড়ে না।
কাজ

6
রেফারেন্স উত্সটি দেখে এবং পরিবর্তন সনাক্তকরণ কীভাবে কাজ করেছে তা দেখে আপনি নিজেরাই এই প্রশ্নের উত্তর দিতে সক্ষম হয়েছিলেন । প্রত্যেকে কেবল রেফারেন্স উত্সটি উপস্থিত থাকার কথা জানেন না, কেবল শব্দটি ছড়িয়ে দিয়েছেন :)
ক্রিস্টোফার কারেনস

2
মাত্র কৌতূহল ছাড়াই: আপনি কি কোডটি একটি আসল-বিশ্বের টুকরোটিতে এই সমস্যাটি পেয়েছিলেন?
কেন

উত্তর:


119

সমস্যাটি হ'ল যেভাবে List<T>পরিবর্তনগুলি সনাক্ত করে তা হ'ল সংস্করণ ক্ষেত্র, ধরণের intএবং প্রতিটি পরিবর্তনের উপর বাড়িয়ে তোলা। সুতরাং, যদি আপনি পুনরাবৃত্তির মধ্যে তালিকার 2 32 সংশোধনীগুলির ঠিক একাধিক সংখ্যক তৈরি করে থাকেন তবে এটি সনাক্তকরণের হিসাবে যতদূর অদৃশ্য সেই পরিবর্তনগুলি রেন্ডার করবে। (এটা থেকে ওভারফ্লো হবে থেকে এবং শেষ পর্যন্ত তার প্রারম্ভিক মান ফিরে পেতে।)int.MaxValueint.MinValue

আপনি যদি আপনার কোড সম্পর্কে বেশ কিছু পরিবর্তন করেন - 2 এর পরিবর্তে 1 বা 3 মান যুক্ত করুন বা আপনার অভ্যন্তরীণ লুপটির পুনরাবৃত্তির সংখ্যা 1 দ্বারা কম করুন, তবে এটি প্রত্যাশার মতো ব্যতিক্রম ছুঁড়ে ফেলবে।

(এটি নির্দিষ্ট আচরণের পরিবর্তে বাস্তবায়নের বিশদ - এবং এটি একটি বাস্তবায়ন বিশদ যা খুব বিরল ক্ষেত্রে একটি বাগ হিসাবে পর্যবেক্ষণ করা যেতে পারে। তবে এটি কোনও বাস্তব প্রোগ্রামে সমস্যা সৃষ্টি করে দেখা খুব অস্বাভাবিক হবে))


5
কেবলমাত্র রেফারেন্সের জন্য: প্রাসঙ্গিক উত্স কোড , দ্রষ্টব্য যে _versionক্ষেত্রটি একটি int
লুকাস ট্রজেসনিউস্কি

1
হ্যাঁ, এটি ঠিক ঠিকঠাকভাবে সেট আপ করা হয়েছে যাতে লুপ শেষ হওয়ার পরে, _version এর মান -2 থাকে .... তারপরে 6 এবং 7 যোগ করে এটি 0 টি করে রাখে, তালিকাটি এটি অপরিশোধিত বলে মনে হয়।
কাজ

4
আমি নিশ্চিত নই যে এটিকে একটি "বাস্তবায়ন বিশদ" বলা উচিত, কারণ সেই বাস্তবায়ন সিদ্ধান্তের একটি পার্শ্ব প্রতিক্রিয়া রয়েছে, এমনকি যদি হওয়ার সম্ভাবনা নাও থাকে তবে এটি আসল। অনুমান (বা কমপক্ষে ডক) বলে যে এটি একটি নিক্ষেপ করা উচিত InvalidOperationException, যা আসলে সবসময় সত্য নয়। অবশ্যই এটি "বাস্তবায়ন বিশদ" এর সংজ্ঞা উপর নির্ভর করে।
কেন

3
জন স্কিটি, আপনি কি প্রোগ্রামিং ল্যাঙ্গুয়েজ ডিজাইনার? (গুগলের সাথে সম্পর্কিত কোনও কিছুই খুঁজে পাওয়া যায়নি) কেন আপনারও এই জ্ঞান রয়েছে তা কিছুটা কৌতূহলী। এই প্রশ্নটি স্ট্যাক ওভারফ্লোয়ের "শক্তি" দেখার জন্য কিছুটা টিজ হয়েছিল।
মিথ্যা কথা বলছেনস্ক্রিয়

6
@ লাইটিংঅনসস্কি: না, যদিও আমি সি # ভাষার অনুসরণ ও সমালোচনা করার ক্ষেত্রে ভাষা ডিজাইনার হতে খেলতে পছন্দ করি। আমি সি # 5 এর মানককরণের জন্য ECMA-334 প্রযুক্তিগত গ্রুপেও আছি ... সুতরাং আমি গর্তগুলি বেছে নেব কিন্তু বাস্তব ভাষার নকশা কাজটি করব না :)
জন স্কিটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.