সি # তে আইডিস্পোজেবল বনাম ডেস্ট্রাক্টর ব্যবহারের মধ্যে পার্থক্য কী?


101

আমি কখন কোনও ক্লাসে আইডিসপোজকে কোনও ডেস্ট্রাক্টরের বিপরীতে প্রয়োগ করব? আমি এই নিবন্ধটি পড়েছি , তবে আমি এখনও বিষয়টিটি অনুপস্থিত।

আমার ধারণাটি হ'ল আমি যদি কোনও জিনিসে আইডিসপোজ প্রয়োগ করি তবে আবর্জনা সংগ্রহকারী এটি করার অপেক্ষার বিরোধী হিসাবে আমি স্পষ্টভাবে এটি 'ধ্বংস' করতে পারি। এটা কি সঠিক?

তার মানে কি আমার সর্বদা স্পষ্টভাবে কোনও বস্তুর উপর ডিসপোজ কল করা উচিত? এর কয়েকটি সাধারণ উদাহরণ কি কি?


5
প্রকৃতপক্ষে, আপনার প্রতিটি নিষ্পত্তিযোগ্য বস্তুতে ডিসপোজ কল করা উচিত আপনি সহজেই usingকনস্ট্রাক্ট ব্যবহার করে এটি করতে পারেন ।
লুক টুরাইল

আহ, এটা বোঝা যায়। আমি সর্বদা ভাবছিলাম যে ফাইল স্ট্রিমের জন্য 'ব্যবহার' বিবৃতিটি কেন ব্যবহার করা হয়েছিল। আমি জানি যে এটির অবজেক্টের ক্ষেত্রের সাথে কিছু করার ছিল তবে আমি এটি আইডিপোজেবল ইন্টারফেসের সাথে প্রসঙ্গে রাখিনি।
জর্ডান পারমার 14

5
একটি গুরুত্বপূর্ণ বিষয় মনে রাখবেন যে চূড়ান্তকরণকারীর দ্বারা কোনও শ্রেণীর কোনও পরিচালিত সদস্যদের অ্যাক্সেস করা উচিত নয় , কারণ এই সদস্যরা আর বৈধ উল্লেখযোগ্য হতে পারে না।
ড্যান ব্রায়ান্ট

উত্তর:


126

একটি চূড়ান্তকরণকারী (ওরফে ডেস্ট্রাক্টর) আবর্জনা সংগ্রহের (জিসি) অংশ - এটি যখন ঘটে তখনই (বা এমনকি যদি হয়) এটি অনির্দিষ্ট হয়, কারণ জিসি সাধারণত মেমরির চাপের ফলে ঘটে (যেমন আরও জায়গার প্রয়োজন হয়)। ফাইনালাইজারগুলি সাধারণত পরিচালনা না করা সম্পদ পরিষ্কার করার জন্য ব্যবহৃত হয় , যেহেতু পরিচালিত সংস্থাগুলির নিজস্ব সংগ্রহ / নিষ্পত্তি হবে।

অতএব IDisposable, নির্ধারিতভাবে অবজেক্টগুলি পরিষ্কার করার জন্য ব্যবহৃত হয় , এখন এখন। এটি বস্তুর স্মৃতি সংগ্রহ করে না (এটি এখনও জিসির অন্তর্গত) - তবে ফাইল, ডাটাবেস সংযোগ ইত্যাদি বন্ধ করার জন্য ব্যবহৃত হয়

এর উপর পূর্ববর্তী প্রচুর বিষয় রয়েছে:

পরিশেষে, দ্রষ্টব্য যে কোনও জিনিসের IDisposableচূড়ান্তকরণ করাও অস্বাভাবিক নয় ; এক্ষেত্রে , Dispose()সাধারণত কল হয় GC.SuppressFinalize(this), অর্থাত্ জিসি চূড়ান্তকরণকারী চালায় না - এটি কেবল স্মৃতিটিকে দূরে ফেলে দেয় (অনেক সস্তা)। আপনি যদি বিষয়টিকে ভুলে যান তবে ফাইনালাইজারটি এখনও চলে Dispose()


ধন্যবাদ! এটা নিখুঁত জ্ঞান করে তোলে। আমি দুর্দান্ত সাড়া প্রশংসা করি।
জর্ডান পারমার 14

27
একটি অতিরিক্ত কথা বলতে হবে। আপনার ক্লাসে ফাইনালাইজার যুক্ত করবেন না যদি না আপনি সত্যই সত্যই প্রয়োজন হয়। যদি আপনি একটি চূড়ান্তকরণকারী (বিনষ্টকারী) যোগ করেন তবে জিসিকে এটিকে কল করতে হবে (এমনকি একটি খালি চূড়ান্তকরণকারী) এবং এটি কল করতে বস্তুটি সর্বদা জেনার 1 জঞ্জাল সংগ্রহ থেকে বেঁচে থাকবে। এটি জিসিকে বাধা দেয় এবং কমিয়ে দেবে। উপরের কোডটিতে সাপ্রেসফাইনালাইজকে কল করার জন্য মার্ক বলেছে
কেভিন জোন্স

1
সুতরাং চূড়ান্তকরণ হ'ল পরিচালনাহীন সংস্থানসমূহকে মুক্তি দেওয়া। তবে ডিসপোজটি পরিচালনা করা এবং পরিচালনা না করা সংস্থানগুলি ছেড়ে দিতে ব্যবহৃত হতে পারে?
গা_়_কানাইট

2
@ ডার্ক হ্যাঁ; কারণ পরিচালনার শৃঙ্খলের নিচে levels টি স্তর একটি নিয়ন্ত্রণহীন হতে পারে যা তাত্ক্ষণিক ক্লিনআপ প্রয়োজন
মার্ক গ্র্যাভেল

1
ফাইনালাইজারযুক্ত কেভিনজোনস অবজেক্টসগুলিতে 1, নয় 1 জেনের বেঁচে থাকার নিশ্চয়তা আছে? আমি এটি নেট পারফরম্যান্স নামে একটি বইতে পড়েছি।
ডেভিড ক্ল্যাম্পফনার

25

Finalize()পদ্ধতির ভূমিকাটি নিশ্চিত করা হয় যে আবর্জনা সংগ্রহের সময় কোনও .NET অবজেক্টটি নিয়ন্ত্রণহীন সংস্থানগুলি পরিষ্কার করতে পারে । তবে, আবর্জনা সংগ্রহের উপর নির্ভর করে পরিবর্তে ডাটাবেস সংযোগ বা ফাইল হ্যান্ডলারের মতো অবজেক্টগুলি যত তাড়াতাড়ি সম্ভব মুক্তি দেওয়া উচিত। তার জন্য আপনার IDisposableইন্টারফেস প্রয়োগ করা উচিত এবং Dispose()পদ্ধতিতে আপনার সংস্থানগুলি ছেড়ে দেওয়া উচিত ।


9

এমএসডিএন সম্পর্কে খুব ভাল বর্ণনা রয়েছে :

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

আবর্জনা সংগ্রাহকের সাথে একযোগে অব্যবহৃত পরিচালিত সংস্থানগুলিকে সুস্পষ্টভাবে প্রকাশ করতে এই ইন্টারফেসের ডিসপোজ পদ্ধতিটি ব্যবহার করুন । একটি বস্তুর ভোক্তা যখন বস্তুর আর প্রয়োজন হয় এই পদ্ধতি কল করতে পারেন।


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

1
যদি একটি স্বল্প-স্থায়ী অবজেক্ট দীর্ঘস্থায়ী অবজেক্টের কোনও ইভেন্টে সদস্যতা গ্রহণ করে (যেমন এটি স্বল্প-জীবিত অবজেক্টের জীবদ্দশায় ঘটে যাওয়া কোনও পরিবর্তন সম্পর্কে অবহিত হওয়ার অনুরোধ করে), ব্যর্থ হওয়ার পরে এই জাতীয় ইভেন্টটিকে একটি নিয়ন্ত্রণহীন উত্স হিসাবে বিবেচনা করা উচিত এই সদস্যতাটি বাতিল করুন ইভেন্টটি স্বল্প-স্থায়ী অবজেক্টের আজীবন দীর্ঘকালীন অবজেক্টের মতো বাড়িয়ে দেবে। যদি হাজার হাজার বা লক্ষ লক্ষ স্বল্প-জীবিত অবজেক্টগুলি কোনও ইভেন্টে সাবস্ক্রাইব করে তবে সদস্যতা ছাড়াই ছেড়ে দেওয়া হয়, যা মেমরি বা সিপিইউ ফাঁসের কারণ হতে পারে (যেহেতু প্রতিটি সাবস্ক্রিপশন প্রক্রিয়া করার জন্য প্রয়োজনীয় সময় বাড়বে)।
সুপারক্যাট

1
পরিচালিত কোডের মধ্যে নিয়ন্ত্রণহীন সংস্থানগুলির সাথে জড়িত আরেকটি দৃশ্যটি পুলগুলি থেকে অবজেক্ট বরাদ্দ হবে। বিশেষত কোডটি .NET মাইক্রো ফ্রেমওয়ার্কে চালিত হওয়া প্রয়োজন (যার আবর্জনা সংগ্রহকারী ডেস্কটপ মেশিনগুলির তুলনায় অনেক কম দক্ষ) কোডের জন্য যেমন কাঠামোগুলির একটি অ্যারে থাকতে পারে, যার প্রত্যেকটি "ব্যবহৃত" হিসাবে চিহ্নিত হতে পারে বা "ফ্রি"। একটি বরাদ্দের অনুরোধে এমন একটি কাঠামো পাওয়া উচিত যা বর্তমানে "মুক্ত" হিসাবে চিহ্নিত রয়েছে, এটি "ব্যবহৃত" চিহ্নিত করুন এবং এটিতে একটি সূচক ফেরত দিন; একটি মুক্তির অনুরোধে কোনও কাঠামো "মুক্ত" হিসাবে চিহ্নিত করা উচিত। যদি কোনও বরাদ্দের অনুরোধটি যেমন 23 দেয়, তবে ...
সুপারক্যাট 18'15

1
... যদি কোডটি অ্যারের মালিককে কখনই অবহিত করে না যে এটির জন্য আর # 23 আইটেমের প্রয়োজন নেই, অ্যারে স্লট অন্য কোনও কোড দ্বারা কখনই ব্যবহারযোগ্য হবে না। অ্যারের স্লটগুলির বাইরে এ জাতীয় ম্যানুয়াল বরাদ্দ ডেস্কটপ কোডে প্রায়শই ব্যবহৃত হয় না কারণ জিসি বেশ দক্ষ, তবে কোডটিতে মাইক্রো ফ্রেমওয়ার্কে চলমান এটি একটি বিশাল পার্থক্য করতে পারে।
সুপারক্যাট

8

কেবলমাত্র একটি সি # ডিস্ট্রাক্টরের মধ্যে থাকা উচিত এই লাইনটি:

Dispose(False);

এটাই. আর কিছুই আর সেই পদ্ধতিতে হওয়া উচিত নয়।


3
এটি নেট ডকুমেন্টেশনে মাইক্রোসফ্ট দ্বারা প্রস্তাবিত ডিজাইনের প্যাটার্ন, তবে যখন আপনার অবজেক্ট আইডিজিপোজেবল হয় না তখন এটি ব্যবহার করবেন না। msdn.microsoft.com/en-us/library/fs2xkftw%28v=vs.110%29.aspx
জেডবিল

1
ফাইনালাইজারের সাথে ক্লাস অফার করার কোনও কারণ আমি ভাবতে পারি না যার ডিসপোজ পদ্ধতিও নেই।
জোনাথন অ্যালেন

4

আপনার সর্বদা কল Disposeকরা উচিত কিনা এই বিষয়ে আপনার প্রশ্নটি একটি উত্তপ্ত বিতর্ক। .NET সম্প্রদায়ের সম্মানিত ব্যক্তিদের কাছ থেকে আকর্ষণীয় দৃষ্টিভঙ্গির জন্য এই ব্লগটি দেখুন ।

ব্যক্তিগতভাবে, আমি মনে করি জেফরি রিখটারের অবস্থান যে কলিং Disposeবাধ্যতামূলক নয় তা অবিশ্বাস্যভাবে দুর্বল। তিনি তার মতামতকে ন্যায়সঙ্গত করার জন্য দুটি উদাহরণ দেন।

প্রথম উদাহরণে তিনি বলেছিলেন যে Disposeমূলধারার পরিস্থিতিতে উইন্ডোজ ফর্ম নিয়ন্ত্রণগুলিতে কল করা ক্লান্তিকর এবং অপ্রয়োজনীয়। তবে তিনি তা উল্লেখ করতে ব্যর্থ হনDispose মূলধারার দৃশ্যে নিয়ন্ত্রণ পাত্রে আসলে স্বয়ংক্রিয়ভাবে বলা হয়।

দ্বিতীয় উদাহরণে তিনি বলেছিলেন যে কোনও বিকাশকারী ভুলভাবে ধরে নিতে IAsyncResult.WaitHandleপারে যে সম্পত্তিটি অলসভাবে ওয়েট হ্যান্ডেলটি অযৌক্তিক পারফরম্যান্স জরিমানার ফলস্বরূপ প্রবর্তন করে তা না বুঝে আক্রমণাত্মকভাবে নিষ্পত্তি করা উচিত। তবে, এই উদাহরণটির সাথে সমস্যাটি হ'ল IAsyncResultনিজেই কোনও IDisposableজিনিসগুলি নিয়ে কাজ করার জন্য মাইক্রোসফ্টের নিজস্ব প্রকাশিত নির্দেশিকাগুলি মেনে চলেন না । এটি যদি কোনও শ্রেণীর কোনও IDisposableধরণের রেফারেন্স থাকে তবে ক্লাসটি নিজেই প্রয়োগ করা উচিত IDisposable। যদি IAsyncResultসেই নিয়ম অনুসরণ করা হয় তবে তার নিজস্বDispose পদ্ধতি সিদ্ধান্ত নিতে পারে যে কোনটি তার নির্বাচনী সদস্যের নিষ্পত্তি করার দরকার regarding

সুতরাং কারও কাছে আরও জোরালো যুক্তি না থাকলে আমি "সর্বদা কল ডিসপোজ" শিবিরে থাকতে যাব এই বোঝার সাথে যে সেখানে কিছু ফ্রিঞ্জের ঘটনা ঘটতে চলেছে যা বেশিরভাগ দুর্বল নকশার পছন্দ থেকে বেরিয়ে আসে।


3

এটা সত্যিই খুব সহজ। আমি জানি যে এর উত্তর দেওয়া হয়েছে তবে আমি আবার চেষ্টা করব তবে যথাসম্ভব সহজ রাখার চেষ্টা করব।

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

আইডিজিপোসিবল ব্যবহার করা উচিত যখনই আপনার কাছে এমন কোনও বস্তু থাকে যা এমন সংস্থান তৈরি করে যা পরিষ্কার করার প্রয়োজন হয় (যেমন, ফাইল এবং গ্রাফিক্স হ্যান্ডলগুলি)। প্রকৃতপক্ষে, অনেকের যুক্তি রয়েছে যে উপরোক্ত কারণগুলির কারণে আপনি কোনও বিধ্বংসককে যা কিছু রেখেছিলেন তা পুতিন আইডিজিপোজেবল হতে হবে।

ফাইনালাইজারটি কার্যকর করা হলে বেশিরভাগ ক্লাস ডিসপোজ কল করবে তবে এটি কেবল নিরাপদ প্রহরী হিসাবে রয়েছে এবং কখনও নির্ভর করা উচিত নয়। আপনি যখন এটি সম্পন্ন করেন তখন আইডিস্পোজেবল কার্যকর করে এমন কোনও কিছু স্পষ্টভাবে নিষ্পত্তি করা উচিত। আপনি যদি আইডিস্পোজেবল বাস্তবায়ন করেন তবে আপনার চূড়ান্তকরণে নিষ্পত্তি কল করা উচিত। উদাহরণস্বরূপ http://msdn.microsoft.com/en-us/library/system.idisposable.aspx দেখুন ।


না, আবর্জনা সংগ্রহকারী কখনও ডিসপোজ () কল করেন না। এটি কেবল চূড়ান্তকারীকে কল করে।
মার্ক গ্র্যাভেল

স্থির। ক্লাসগুলি তাদের চূড়ান্তকরণে নিষ্পত্তি কল করার কথা রয়েছে, তবে তাদের দরকার নেই।
দায়েগল

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