আপনার কি অবজেক্টগুলি নিষ্পত্তি করতে হবে এবং সেগুলি বাতিল করতে হবে?


310

আপনার কি জিনিসগুলি নিষ্পত্তি করে এলোমেলো করার দরকার আছে, বা আবর্জনা সংগ্রহকারী যখন তারা সুযোগের বাইরে চলে যান তখন তাদের পরিষ্কার করবেন?


4
একটি sensক্যমত্য বলে মনে হচ্ছে যে আপনাকে অবজেক্টটি শূন্য করতে হবে না, তবে কি আপনাকে ডিসপোজ () করতে হবে?
সিজে 7

3
জেফ যেমন বলেছিলেন: কোডিংহরর.com
blog

9
আমার পরামর্শ সর্বদা নিষ্পত্তি হয় যদি কোনও বস্তু আইডিস্পোজেবল কার্যকর করে। প্রতিবার একটি ব্যবহার ব্লক ব্যবহার করুন। অনুমান করবেন না, এটিকে সুযোগ পর্যন্ত ছেড়ে দেবেন না। যদিও আপনাকে জিনিসগুলি বাতিল করতে হবে না। একটি অবজেক্ট মাত্র সুযোগের বাইরে চলে গেছে।
পিটার

11
: @peter: দো WCF ক্লায়েন্ট প্রক্সি সঙ্গে ব্লক "ব্যবহার" ব্যবহার না msdn.microsoft.com/en-us/library/aa355056.aspx
nlawalker

9
যাইহোক, আপনি আপনার Dispose()পদ্ধতির অভ্যন্তরে নালার জন্য কিছু উল্লেখ সেট করতে চান ! এটি এই প্রশ্নের একটি সূক্ষ্ম প্রকরণ, তবে গুরুত্বপূর্ণ কারণ নিষ্পত্তি করা অবজেক্টটি এটি "সুযোগের বাইরে চলে" যাচ্ছে কিনা তা জানতে পারে না (কল Dispose()করা কোনও গ্যারান্টি নয়)। এখানে আরও: স্ট্যাকওভারফ্লো.com
কেভিন পি। রাইস

উত্তর:


239

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

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

usingআপনার প্রোগ্রামটি usingস্টেটমেন্টের সুযোগ ছেড়ে দিলে আপনি কোনও বিষয় স্বয়ংক্রিয়ভাবে নিষ্পত্তি করতে আপনি বিবৃতিটি ব্যবহার করতে পারেন ।

using (MyIDisposableObject obj = new MyIDisposableObject())
{
    // use the object here
} // the object is disposed here

যা কার্যত সমান:

MyIDisposableObject obj;
try
{
    obj = new MyIDisposableObject();
}
finally
{
    if (obj != null)
    {
        ((IDisposable)obj).Dispose();
    }
}

4
যদি আপত্তিটি একটি রেফারেন্স টাইপ হয় তবে শেষ অবধি ব্লকের সমতুল্য:if (obj != null) ((IDisposable)obj).Dispose();
র্যান্ডি মনিকা 24

1
@ টুজো: ধন্যবাদ! যে প্রতিফলিত সম্পাদিত।
জাচ জনসন

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

@ র্যান্ডিলেভি আপনার কাছে কি রেফারেন্স আছে? ধন্যবাদ
বেসিক

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

137

বস্তুগুলি সি #+ তে যেমন কখনও স্কোপের বাইরে যায় না। এগুলি আর ব্যবহার করা হয় না, তখন তাদের আবশ্যকভাবে আবর্জনা সংগ্রাহকরা তাদের সাথে ডিল করেন। এটি সি ++ এর চেয়ে আরও জটিল পদ্ধতি যেখানে ভেরিয়েবলের ব্যাপ্তি পুরোপুরি হ্রাসকারী। সিএলআর আবর্জনা সংগ্রহকারী সক্রিয়ভাবে তৈরি করা সমস্ত বস্তুর মধ্য দিয়ে যায় এবং যদি সেগুলি ব্যবহার করা হয় তবে তা কার্যকর হয়।

কোনও বস্তু একটি ফাংশনে "সুযোগের বাইরে" যেতে পারে তবে যদি এর মানটি ফিরে আসে, তবে জিসি কলিং ফাংশনটি রিটার্ন মান ধরে রাখে বা না তা সন্ধান করবে।

অবজেক্টের রেফারেন্স সেট nullকরা অপ্রয়োজনীয় কারণ আবর্জনা সংগ্রহের কাজ করে কোন বস্তুটি অন্যান্য বস্তুগুলির দ্বারা রেফারেন্স করা হচ্ছে তা নিয়ে কাজ করে।

অনুশীলনে, আপনাকে ধ্বংস সম্পর্কে চিন্তা করার দরকার নেই, এটি কেবল কাজ করে এবং এটি দুর্দান্ত :)

DisposeIDisposableআপনি যখন তাদের সাথে কাজ শেষ করে তখন কার্যকর করে এমন সমস্ত অবজেক্টগুলিকে অবশ্যই ডাকা হবে । সাধারণত আপনি usingএই জাতীয় বস্তুগুলির সাথে একটি ব্লক ব্যবহার করবেন :

using (var ms = new MemoryStream()) {
  //...
}

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

আসল পরিবর্তনশীল সুযোগ

উভয় ভাষায় ভেরিয়েবল কেবল একই স্কোপ হিসাবে এটি সংজ্ঞায়িত হিসাবে ব্যবহৃত হতে পারে - শ্রেণি, ফাংশন বা ব্রেস দ্বারা আবদ্ধ একটি বিবৃতি ব্লক। সূক্ষ্ম পার্থক্য, তবে, সি # তে, ভেরিয়েবলগুলি নেস্টেড ব্লকে পুনরায় সংজ্ঞায়িত করা যায় না।

সি ++ এ, এটি পুরোপুরি আইনী:

int iVal = 8;
//iVal == 8
if (iVal == 8){
    int iVal = 5;
    //iVal == 5
}
//iVal == 8

সি # তে, তবে আপনি এএ সংকলক ত্রুটি পান:

int iVal = 8;
if(iVal == 8) {
    int iVal = 5; //error CS0136: A local variable named 'iVal' cannot be declared in this scope because it would give a different meaning to 'iVal', which is already used in a 'parent or current' scope to denote something else
}

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

public static void Scope() {
    int iVal = 8;
    if(iVal == 8) {
        int iVal2 = 5;
    }
}

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

.method public hidebysig static void  Scope() cil managed
{
  // Code size       19 (0x13)
  .maxstack  2
  .locals init ([0] int32 iVal,
           [1] int32 iVal2,
           [2] bool CS$4$0000)

//Function IL - omitted
} // end of method Test2::Scope

সি ++ সুযোগ এবং অবজেক্টের আজীবন

যখনই কোনও সি ++ পরিবর্তনশীল, স্ট্যাকের উপর বরাদ্দ করা হয়, সুযোগের বাইরে চলে যায় এটি ধ্বংস হয়ে যায়। মনে রাখবেন যে সি ++ এ আপনি স্ট্যাক বা গাদাতে অবজেক্ট তৈরি করতে পারেন। আপনি যখন এগুলি স্ট্যাকে তৈরি করেন, একবার মৃত্যুদন্ড কার্যকর করার সুযোগটি ছেড়ে যায়, তারা স্ট্যাকটি পপ করে ফেলে এবং ধ্বংস হয়ে যায়।

if (true) {
  MyClass stackObj; //created on the stack
  MyClass heapObj = new MyClass(); //created on the heap
  obj.doSomething();
} //<-- stackObj is destroyed
//heapObj still lives

যখন সি ++ অবজেক্টগুলি গাদাতে তৈরি করা হয়, তাদের অবশ্যই স্পষ্টভাবে ধ্বংস করা উচিত, অন্যথায় এটি মেমরি ফাঁস হয়। স্ট্যাক ভেরিয়েবলের সাথে এ জাতীয় কোনও সমস্যা নেই।

সি # অবজেক্ট লাইফটাইম

সিএলআর-তে অবজেক্টস (অর্থাত্ রেফারেন্স প্রকারের) সর্বদা পরিচালিত হিপগুলিতে তৈরি হয়। এটি আবার অবজেক্ট ক্রিয়েশন সিনট্যাক্স দ্বারা আরও শক্তিশালী হয়। এই কোড স্নিপেট বিবেচনা করুন।

MyClass stackObj;

সি ++ MyClassএ এটি স্ট্যাকের উপর একটি উদাহরণ তৈরি করবে এবং এর ডিফল্ট কনস্ট্রাক্টরকে কল করবে। সি # তে এটি শ্রেণীর একটি রেফারেন্স তৈরি করবে MyClassযা কোনও কিছুর প্রতি নির্দেশ দেয় না। শ্রেণীর উদাহরণ তৈরির একমাত্র উপায় হ'ল newঅপারেটর ব্যবহার করে :

MyClass stackObj = new MyClass();

একটি উপায়ে, সি # অবজেক্ট অনেকগুলি অবজেক্টের মতো যা newসি ++ তে সিনট্যাক্স ব্যবহার করে তৈরি করা হয় - সেগুলি হিপে তৈরি করা হয় তবে সি ++ অবজেক্টগুলির বিপরীতে এগুলি রানটাইম দ্বারা পরিচালিত হয়, সুতরাং আপনাকে সেগুলি ধ্বংস করার বিষয়ে চিন্তা করার দরকার নেই।

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

সি # অবজেক্টের রেফারেন্স

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

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

.NET অবজেক্টগুলি অনেকটা ছাদের নীচে হিলিয়াম বেলুনগুলির মতো। যখন ছাদটি খোলা হয় (জিসি চালিত হয়) - অব্যবহৃত বেলুনগুলি ভেসে বেড়ায়, এমনকি সেখানে এমন একাধিক বেলুনের দল থাকতে পারে যা একসাথে জড়িত are

.NET GC প্রজন্মের GC এবং চিহ্ন এবং সুইপের সংমিশ্রণ ব্যবহার করে। জেনারেশনাল অ্যাপ্রোচটিতে রানটাইমের পক্ষে যুক্ত হওয়া বিষয়গুলিকে সর্বাধিক বরাদ্দ দেওয়া হয়েছে, কারণ এগুলি অব্যবহৃত হওয়ার সম্ভাবনা বেশি বেশি এবং চিহ্ন এবং সুইপ জড়িত রানটাইম পুরো অবজেক্টের গ্রাফের মধ্য দিয়ে যাওয়া এবং যদি অবজেক্ট গ্রুপ নেই তবে অবধি কাজ করা জড়িত। এটি পর্যাপ্তভাবে বিজ্ঞপ্তি নির্ভরতা সমস্যা নিয়ে কাজ করে।

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


1
@ ইগোর: 'সুযোগের বাইরে' বলতে গেলে আমার অর্থ হ'ল অবজেক্টের রেফারেন্স প্রসঙ্গের বাইরে এবং বর্তমান স্কোপগুলিতে উল্লেখ করা যায় না। অবশ্যই এটি সি # তে এখনও ঘটে।
সিজে 7

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

1
@ ক্রেইগ জনস্টন: ব্লগস.এমএসএনএন / বি / তারিকগু / অর্চিভ / ২০০৪ /০ //২০১/0 / ২৩ / ১৯২42২২.এএসপিএক্স দেখুন : "কোনও স্থানীয় পরিবর্তনশীল সুযোগের অবসান না হওয়া অবধি লাইভ থাকবে এমন কোনও গ্যারান্টি নেই। রানটাইমটি কোডটি বিশ্লেষণ করতে এবং একটি নির্দিষ্ট পয়েন্টের বাইরে ভেরিয়েবলের আর কোনও ব্যবহারের কী নেই তা নির্ধারণ করতে নিখরচায় রয়েছে এবং অতএব সেই পরিবর্তনশীলটিকে সেই বিন্দুটির বাইরে রাখবেন না (অর্থাত্ উদ্দেশ্যগুলির জন্য এটি রুট হিসাবে বিবেচনা করবেন না) জিসির)। "
রেন্ডি

1
@ টুজো: সত্য। জিসি.কীপএলাইভ এটাই।
স্টিভেন সুদিত

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

18

অন্যরা যেমন বলেছে Disposeযে ক্লাসটি প্রয়োগ করে আপনি অবশ্যই কল করতে চান IDisposable। আমি এটি সম্পর্কে মোটামুটি অনমনীয় অবস্থান গ্রহণ করি। কিছু দাবি করতে পারে যে উদাহরণস্বরূপ, কল Disposeকরা DataSetঅর্থহীন কারণ তারা এটিকে বিচ্ছিন্ন করে দেখেছিল যে এটি অর্থবহ কিছু করে না anything তবে, আমি মনে করি যে যুক্তিটিতে প্রচুর ভুল রয়েছে।

পড়ুন এই বিষয়ে সম্মানিত ব্যক্তি দ্বারা একটি আকর্ষণীয় বিতর্ক জন্য। তারপরে আমার যুক্তিটি এখানে পড়ুন কেন আমি মনে করি কেন জেফারি রিখটারটি ভুল শিবিরে রয়েছে।

এখন, আপনার কোনও রেফারেন্স সেট করা উচিত কিনা তা নিয়ে null। উত্তর না হয়। আমাকে আমার কোডটি নীচের কোড দিয়ে চিত্রিত করুন।

public static void Main()
{
  Object a = new Object();
  Console.WriteLine("object created");
  DoSomething(a);
  Console.WriteLine("object used");
  a = null;
  Console.WriteLine("reference set to null");
}

সুতরাং আপনি কখন মনে করেন যে রেফারেন্স করা অবজেক্টটি aসংগ্রহের জন্য যোগ্য? যদি আপনি কল করার পরে বলেন a = nullতবে আপনি ভুল। আপনি যদি Mainপদ্ধতিটি সম্পূর্ণ করার পরে বলেন তবে আপনিও ভুল। সঠিক উত্তরটি হ'ল কল করার সময় এটি কোনও সময়ে সংগ্রহের জন্য উপযুক্ত DoSomething। সেটা ঠিক. রেফারেন্স সেট করার আগে এবং সম্ভবত কলটি শেষ হওয়ার আগেই এটি যোগ্য । এটি কারণ যে জেআইটি সংকলক সনাক্ত করতে পারে যখন অবজেক্টের রেফারেন্সগুলি এখনও রুট করা সত্ত্বেও আর তত্পর হয় না।nullDoSomething


3
কোন aশ্রেণিতে যদি কোনও প্রাইভেট সদস্য ক্ষেত্র থাকে? যদি aজিসি নালার জন্য সেট না করা হয় তবে কোনও পদ্ধতিতে aআবার ব্যবহার করা হবে কিনা তা জানার কোনও উপায় নেই , তাই না? এভাবে aসম্পূর্ণ সমেত শ্রেণি সংগ্রহ না করা অবধি সংগ্রহ করা হবে না। কোন?
কেভিন পি। রাইস

4
@ কেভিন: সঠিক। যদি aকোনও শ্রেণীর সদস্য এবং aসমেত শ্রেণিটি এখনও মূলে থাকে এবং ব্যবহারের পরে থাকে তবে এটিও চারপাশে ঝুলবে। এটি এমন একটি দৃশ্যের যেখানে সেট nullকরা সুবিধাজনক হতে পারে।
ব্রায়ান গিডন

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

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

13

আপনার কখনই সি # তে অবলম্বন করার দরকার নেই set সংকলক এবং রানটাইম যখন তাদের আর সুযোগ নেই তখন তাদের খুঁজে বের করার যত্ন নেবে।

হ্যাঁ, আপনার আইডিজিপোজেবল বাস্তবায়নকারী বস্তুর নিষ্পত্তি করা উচিত।


2
যদি আপনার কোনও বৃহত অবজেক্টের দীর্ঘকালীন (বা এমনকি স্থিতিশীল) রেফারেন্স থাকে তবে wantআপনি এটি সম্পন্ন করার সাথে সাথে এটিকে বাতিল করতে হবে যাতে এটি পুনরায় দাবি করা মুক্ত।
স্টিভেন সুদিত

12
আপনি যদি কখনও "এটির সাথে সম্পন্ন" হন তবে এটি স্থির হওয়া উচিত নয়। যদি এটি স্থির না হয় তবে "দীর্ঘজীবী" হয় তবে এটি সম্পন্ন করার পরে এটির সুযোগের বাইরে থাকা উচিত। নালকে রেফারেন্স সেট করার প্রয়োজনীয়তা কোডের কাঠামো নিয়ে একটি সমস্যা নির্দেশ করে।
ইএমপি

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

1
তবে এটি কোনও অস্থায়ীভাবে ব্যবহার করা হলে এটি কোনও স্থিতিশীল ক্ষেত্রে কোনও কাঁচা তথ্য সঞ্চয় করা উচিত নয় store অবশ্যই, আপনি এটি করতে পারেন, ঠিক এই কারণেই এটি কেবল ভাল অনুশীলন নয়: এরপরে আপনাকে নিজের জীবনকাল ম্যানুয়ালি পরিচালনা করতে হবে।
EMP

2
আপনি এটি প্রক্রিয়া পদ্ধতিতে স্থানীয় ভেরিয়েবলে কাঁচা তথ্য সংরক্ষণ করে এড়াতে পারেন। পদ্ধতিটি প্রসেসড ডেটা ফেরত দেয়, যা আপনি রাখেন, তবে পদ্ধতিটি যখন বের হয় এবং স্বয়ংক্রিয়ভাবে জিসিইড হয় তখন কাঁচা ডেটার স্থানীয় স্থানীয় সুযোগের বাইরে চলে যায়।
EMP

11

আমি এখানে সাধারণ উত্তরটির সাথে একমত যে হ্যাঁ আপনার নিষ্পত্তি করা উচিত এবং না আপনার সাধারণত চলকটি বাতিল করতে হবে না ... তবে আমি উল্লেখ করতে চেয়েছিলাম যে নিষ্পত্তি মূলত মেমরি পরিচালনার ক্ষেত্রে নয়। হ্যাঁ, এটি মেমরির পরিচালনায় সহায়তা করতে (এবং কখনও কখনও করতে) সহায়তা করতে পারে তবে এটির প্রাথমিক উদ্দেশ্য হ'ল দুর্লভ সংস্থানগুলি নির্বিঘ্নে মুক্ত করা।

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

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


11

যদি অবজেক্টটি প্রয়োগ করে IDisposable, তবে হ্যাঁ, আপনার এটি নিষ্পত্তি করা উচিত। অবজেক্টটি স্থানীয় উত্সগুলিতে (ফাইল হ্যান্ডলগুলি, ওএস অবজেক্ট) ঝুলতে পারে যা অন্যথায় অবিলম্বে মুক্তি পায় না। এটি রিসোর্স অনাহার, ফাইল-লকিং সমস্যা এবং অন্যান্য সূক্ষ্ম ত্রুটিগুলি এড়াতে পারে যা অন্যথায় এড়ানো যায়।

এমএসডিএন-তে একটি নিষ্পত্তি পদ্ধতির বাস্তবায়নও দেখুন ।


তবে গ্যারাবেজ সংগ্রাহক ডিসপোজ () কল করবেন না? যদি তাই হয় তবে কেন এটি কল করার দরকার পড়বে?
সিজে 7

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

12
জিসি কখনই ডিসপোজ () এ কল করবে না। জিসি একটি চূড়ান্তকরণকারীকে কল করতে পারে যা কনভেনশন দ্বারা সম্পদ পরিষ্কার করা উচিত।
অ্যাড্রিনিম

@ অ্যাড্রিনিম: mightকল নয় , willকল করুন।
লেপি

2
@ লেপ্পি: চূড়ান্তকরণকারীগুলি নির্ণায়ক নয় এবং ডাকা হতে পারে না (যেমন অ্যাপডোমেনটি লোড করা অবস্থায়)। আপনার যদি ডিটারমিনিস্টিক চূড়ান্তকরণের প্রয়োজন হয় তবে আমার অবশ্যই মনে হয় যা সমালোচনামূলক হ্যান্ডলার বলে তাকে কার্যকর করা উচিত। সিএলআর-এর এই বিষয়গুলির বিশেষ গ্যারান্টি রয়েছে যে সেগুলি চূড়ান্ত হয়েছে (যেমন এটি লো স্মৃতি পরিচালনা করার জন্য চূড়ান্তকরণ কোডটি প্রাক-জিত করে)
অ্যাড্রিনিম

9

যদি তারা আইডিস্পোজেবল ইন্টারফেস প্রয়োগ করে তবে আপনার সেগুলি নিষ্পত্তি করা উচিত। আবর্জনা সংগ্রাহক বাকি যত্ন নেবেন।

সম্পাদনা:using নিষ্পত্তিযোগ্য আইটেমগুলির সাথে কাজ করার সময় কমান্ডটি ব্যবহার করা ভাল :

using(var con = new SqlConnection("..")){ ...

5

যখন কোনও বস্তু প্রয়োগ করে তখন IDisposableআপনাকে কল করা উচিত Dispose(বা Close, কিছু ক্ষেত্রে, এটি আপনার জন্য ডিসপোজ কল করবে)।

আপনাকে সাধারণত অবজেক্টগুলি সেট করতে nullহবে না, কারণ জিসি জানতে পারবেন যে কোনও বস্তু আর ব্যবহার করা হবে না।

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

উদাহরণ:

using (var db = GetDatabase()) {
    // Retrieves array of keys
    var keys = db.GetRecords(mySelection); 

    for(int i = 0; i < keys.Length; i++) {
       var record = db.GetRecord(keys[i]);
       record.DoWork();
       keys[i] = null; // GC can dispose of key now
       // The record had gone out of scope automatically, 
       // and does not need any special treatment
    }
} // end using => db.Dispose is called

4

সাধারণত, শূন্য স্থানে সেট করার দরকার নেই। আমি সর্বদা অপরিশোধিত সম্পদ নিষ্পত্তি করার পরামর্শ দিই।

অভিজ্ঞতা থেকে আমি আপনাকে নিম্নলিখিতগুলি করার পরামর্শ দেব:

  • আপনার যদি আর প্রয়োজন না হয় তবে ইভেন্টগুলি থেকে সাবস্ক্রাইব করুন।
  • প্রতিনিধি বা কোনও অভিব্যক্তি ধারণ করে এমন কোনও ক্ষেত্র নির্ধারণ করুন যদি এটির আর প্রয়োজন হয় না।

আমি উপরের পরামর্শ অনুসরণ না করার প্রত্যক্ষ ফল ছিল এমন সমস্যাগুলি খুঁজে পেতে খুব শক্তভাবে এসেছি।

এটি করার জন্য একটি ভাল জায়গা হ'ল ডিসপোজ () এ, তবে খুব শীঘ্রই আরও ভাল।

সাধারণভাবে, কোনও সামগ্রীর সাথে যদি কোনও রেফারেন্স উপস্থিত থাকে তবে আবর্জনা সংগ্রহকারী (জিসি) অবজেক্টটি আর ব্যবহারে নেই তা নির্ধারণ করতে কয়েক প্রজন্মকে আরও সময় নিতে পারে। সব সময় বস্তু স্মৃতিতে থেকে যায়।

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


1
'ইভেন্টস এবং ডেলিগেটস' সম্পর্কে আপনার অর্থ কী - এগুলি দিয়ে 'পরিষ্কার' করা উচিত?
সিজে 7

@ ক্রেইগ - আমি আমার উত্তর সম্পাদনা করেছি। আশা করি এটি এটি কিছুটা স্পষ্ট করে।
মার্নিক্স ভ্যান ভ্যালেন

3

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

লেপির কথা শুনবেন না।

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

একটি জিনিস ঘটতে পারে তা হ'ল প্রচুর অবজেক্ট খোলা রাখা যেতে পারে। এটি আপনার অ্যাপ্লিকেশনটির মেমরির ব্যবহার ব্যাপকভাবে বাড়িয়ে তুলতে পারে। এটি আসলে মেমরি ফাঁস কিনা, বা আপনার অ্যাপ্লিকেশনটি কেবল প্রচুর স্টাফ করছে কিনা তা নিয়ে কাজ করা কঠিন।

মেমরির প্রোফাইল সরঞ্জামগুলি এ জাতীয় জিনিসগুলিতে সহায়তা করতে পারে তবে এটি জটিল y

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

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


2

আমারও জবাব দিতে হবে। ভেরিয়েবল ব্যবহারের স্থির বিশ্লেষণ থেকে কোডটি একসাথে সারণী তৈরি করে জেআইটি। এই সারণী এন্ট্রিগুলি বর্তমান স্ট্যাক ফ্রেমের "জিসি-রুটস"। নির্দেশিকা নির্দেশকের অগ্রগতির সাথে সাথে those টেবিল এন্ট্রিগুলি অবৈধ হয়ে যায় এবং আবর্জনা সংগ্রহের জন্য তাই প্রস্তুত। অতএব: যদি এটি কোনও স্কোপড ভেরিয়েবল হয়, আপনার এটিকে শূন্য করার দরকার নেই - জিসি এই বস্তুটি সংগ্রহ করবে। এটি কোনও সদস্য বা স্থিতিশীল পরিবর্তনশীল হলে আপনাকে এটিকে শূন্য করতে হবে

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