IDisposable අතුරුමුහුණත නිසි ලෙස භාවිතා කිරීම


1666

මයික්‍රොසොෆ්ට් ප්‍රලේඛනය කියවීමෙන් මම දනිමි , IDisposableඅතුරු මුහුණතේ “ප්‍රාථමික” භාවිතය කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම බව.

මට නම්, “කළමනාකරණය නොකළ” යන්නෙන් අදහස් කරන්නේ දත්ත සමුදා සම්බන්ධතා, සොකට්, කවුළු හැසිරවීම් යනාදියයි. එහෙත්, Dispose()නිදහස් කළමණාකරන සම්පත් සඳහා ක්‍රමවේදය ක්‍රියාත්මක කරන කේතය මම දැක ඇත්තෙමි , එය මට අතිරික්තයක් ලෙස පෙනේ, මන්ද කසළ එකතු කරන්නා සැලකිලිමත් විය යුතුය. එය ඔබ වෙනුවෙන්.

උදාහරණයක් වශයෙන්:

public class MyCollection : IDisposable
{
    private List<String> _theList = new List<String>();
    private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();

    // Die, clear it up! (free unmanaged resources)
    public void Dispose()
    {
        _theList.clear();
        _theDict.clear();
        _theList = null;
        _theDict = null;
    }

මගේ ප්‍රශ්නය නම්, MyCollectionමෙය සාමාන්‍යයෙන් වඩා වේගයෙන් කසළ එකතු කරන්නාගේ නිදහස් මතකය භාවිතා කරයිද?

සංස්කරණය කරන්න : දත්ත සමුදා සම්බන්ධතා සහ බිට්මැප් වැනි කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම සඳහා IDisposable භාවිතා කිරීම පිළිබඳ මේ දක්වා මිනිසුන් හොඳ උදාහරණ කිහිපයක් පළ කර ඇත. ඒ නිසා කැරැල්ල _theListඉහත කේතය දී මිලියන නූල් ද, සහ ඔබ ඒ මතකය නිදහස් කිරීමට අවශ්ය දැන් ඒ වෙනුවට කුණු එකතු බලා වඩා. ඉහත කේතය එය ඉටු කරයිද?


36
මම පිළිගත් පිළිතුරට කැමතියි එය IDisposable භාවිතා කිරීමේ නිවැරදි 'රටාව' ඔබට පවසන නිසා, නමුත් OP ඔහුගේ සංස්කරණයේ සඳහන් කළ පරිදි, එය ඔහු අපේක්ෂිත ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත. IDisposable විසින් GC 'අමතන්නේ නැත, එය වස්තුවක් විනාශ කළ හැකි යැයි සලකුණු කරයි. GC ආරම්භ වන තෙක් බලා සිටීම වෙනුවට 'මේ මොහොතේ' මතකය නිදහස් කර ගැනීමේ සැබෑ ක්‍රමය කුමක්ද? මෙම ප්‍රශ්නය වැඩි සාකච්ඡාවකට සුදුසු යැයි මම සිතමි.
Punit Vora

42
IDisposableකිසිවක් සලකුණු නොකරයි. Disposeඋදාහරණය භාවිතා කරන සම්පත් පිරිසිදු කිරීම සඳහා කළ යුතු දේ මෙම ක්‍රමය මඟින් සිදු කරයි. මෙයට GC සමඟ කිසිදු සම්බන්ධයක් නැත.
ජෝන් සෝන්ඩර්ස්

4
@ ජෝන්. මට තේරෙනවා IDisposable. IDisposable <i> මතකය නිදහස් කිරීමට </ i> උපකාරී වේද යන්න පිළිබඳ OP හි අපේක්ෂිත ප්‍රශ්නයට (සහ පසු විපරම් සංස්කරණයට) පිළිගත් පිළිතුර පිළිතුරු නොදෙන බව මා කීවේ එබැවිනි. IDisposableමතකය නිදහස් කිරීම සමග කිසිදු සම්බන්ධයක් නැති හෙයින් , සම්පත් පමණක්, එවිට ඔබ කීවාක් මෙන්, කළමනාකරණ යොමු කිරීම් කිසිසේත් අහෝසි කිරීමට අවශ්‍ය නැත, ඔහුගේ උදාහරණයේ දී OP කළේ එයයි. ඉතින්, ඔහුගේ ප්‍රශ්නයට නිවැරදි පිළිතුර නම් "නැත, එය නිදහස් මතකයට වේගයෙන් උදව් නොකරයි. ඇත්ත වශයෙන්ම එය නිදහස් මතකයට කිසිසේත් උදව් නොකරයි, සම්පත් පමණි". කෙසේ වෙතත්, ඔබගේ ආදානයට ස්තූතියි.
Punit Vora

9
@desigeek: මෙය එසේ නම්, ඔබ “අයිඩිස්පෝසබල් විසින් ජීසී යනුවෙන් නොකියයි, එය වස්තුවක් විනාශ කළ හැකි යැයි සලකුණු කරයි” යනුවෙන් පැවසිය යුතු නැත
ජෝන් සෝන්ඩර්ස්

5
@desigeek: නිශ්චිතවම මතකය නිදහස් කිරීමට සහතික කළ හැකි ක්‍රමයක් නොමැත. ඔබට GC.Collect () අමතන්න, නමුත් එය ආචාරශීලී ඉල්ලීමක් මිස ඉල්ලීමක් නොවේ. කසළ එකතු කිරීම සඳහා සියලුම ධාවන කෙඳි අත්හිටුවිය යුතුය - ඔබට වැඩිදුර ඉගෙන ගැනීමට අවශ්‍ය නම් .NET ආරක්ෂිත ස්ථාන පිළිබඳ සංකල්පය කියවන්න, උදා: msdn.microsoft.com/en-us/library/678ysw69(v=vs.110). aspx . නූල් අත්හිටුවිය නොහැකි නම්, උදා: කළමනාකරණය නොකළ කේතයට ඇමතුමක් ඇති නිසා, GC.Collect () කිසිසේත් කිසිවක් නොකරනු ඇත.
කොන්ක්‍රීට් ගැනට්

Answers:


2627

බැහැර කිරීමේ කාරණය වන්නේ කළමනාකරණය නොකළ සම්පත් නිදහස් කිරීමයි. එය යම් අවස්ථාවක දී කළ යුතුය, එසේ නොමැති නම් ඒවා කිසි විටෙකත් පිරිසිදු නොකෙරේ. කුණු එකතු දන්නේ නැහැ කොහොමද කැඳවීමට DeleteHandle()වර්ගයේ විචල්ය මත IntPtr, එය දන්නේ නැහැ යන්න එය ඇමතුමක් කිරීමට අවශ්ය නැද්ද DeleteHandle().

සටහන : කළමනාකරණය නොකළ සම්පතක් යනු කුමක්ද? ඔබ එය මයික්‍රොසොෆ්ට් .නෙට් රාමුව තුළ සොයා ගත්තේ නම්: එය කළමනාකරණය කර ඇත. ඔබ එම්එස්ඩීඑන් වටා එබී බැලුවහොත් එය පාලනය කළ නොහැක. .NET රාමුව තුළ ඔබට ලබා ගත හැකි සෑම දෙයක්ම ලස්සන සුවපහසු ලෝකයෙන් පිටතට ගෙන ඒමට ඔබ P / Invoke ඇමතුම් භාවිතා කර ඇති ඕනෑම දෙයක් කළමනාකරණය කර නැත - එය පිරිසිදු කිරීමේ වගකීම දැන් ඔබ සතුය.

කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම සඳහා ඔබ විසින් නිර්මාණය කරන ලද වස්තුවට බාහිර ලෝකයට ඇමතිය හැකි යම් ක්‍රමවේදයක් හෙළි කළ යුතුය. ඔබ කැමති ඕනෑම දෙයක් මෙම ක්‍රමය නම් කළ හැකිය:

public void Cleanup()

හෝ

public void Shutdown()

නමුත් ඒ වෙනුවට මෙම ක්‍රමය සඳහා ප්‍රමිතිගත නමක් ඇත:

public void Dispose()

අතුරු මුහුණතක් පවා නිර්මාණය IDisposableකර ඇත, එයට ඇත්තේ එක් ක්‍රමයක් පමණි:

public interface IDisposable
{
   void Dispose()
}

එබැවින් ඔබ ඔබේ වස්තුව IDisposableඅතුරු මුහුණත නිරාවරණය කිරීමට සලස්වන අතර , එමඟින් ඔබ කළමනාකරණය නොකරන ලද සම්පත් පිරිසිදු කිරීම සඳහා එම තනි ක්‍රමය ලියා ඇති බවට පොරොන්දු වේ:

public void Dispose()
{
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}

ඔබ ඉවරයි. ඔබට වඩා හොඳින් කළ හැකි හැර.


ඔබේ වස්තුව යම් ආකාරයක රාමු බෆරයක් ලෙස 250MB System.Drawing.Bitmap (එනම් .NET කළමනාකරණය කළ බිට්මැප් පන්තිය) වෙන් කර ඇත්නම් කුමක් කළ යුතුද? නිසැකවම, මෙය කළමනාකරණය කළ .NET වස්තුවක් වන අතර කසළ එකතු කරන්නා එය නිදහස් කරයි. නමුත් ඔබට ඇත්ත වශයෙන්ම අවශ්‍ය වන්නේ මෙගාබයිට් 250 ක මතකයක් එහි හිඳගෙන සිටීමයි - කසළ එකතු කරන්නා අවසානයේ පැමිණ එය නිදහස් කරන තෙක් බලා සිටිනවාද? මොන තියෙනවා නම් විවෘත දත්තගබඩා සම්බන්ධතා ? නිසැකවම අපට එම සම්බන්ධතාවය විවෘතව තබා ගැනීමට අවශ්‍ය නැත, GC වස්තුව අවසන් වන තෙක් බලා සිටී.

පරිශීලකයා ඇමතුවේ නම් Dispose()(එයින් අදහස් කරන්නේ ඔවුන් තවදුරටත් වස්තුව භාවිතා කිරීමට අදහස් නොකරන බවයි) එම නාස්තිකාර බිට්මැප් සහ දත්ත සමුදා සම්බන්ධතා ඉවත් නොකරන්නේ ඇයි?

දැන් අපි:

  • කළමනාකරණය නොකළ සම්පත් ඉවත් කරන්න (අපට කළ යුතු නිසා), සහ
  • කළමනාකරණ සම්පත් ඉවත් කරන්න (අපට උදව් කිරීමට අවශ්‍ය නිසා)

එබැවින් Dispose()එම කළමනාකරණය කළ වස්තූන් ඉවත් කිරීම සඳහා අපගේ ක්‍රමය යාවත්කාලීන කරමු :

public void Dispose()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //Free managed resources too
   if (this.databaseConnection != null)
   {
      this.databaseConnection.Dispose();
      this.databaseConnection = null;
   }
   if (this.frameBufferImage != null)
   {
      this.frameBufferImage.Dispose();
      this.frameBufferImage = null;
   }
}

සියලු යහපත් ඔබ වඩා හොඳින් කළ හැකි හැර !


ඔබේ වස්තුව ඇමතීමට පුද්ගලයාට අමතක වුවහොත් කුමක් කළ Dispose()යුතුද? එවිට ඔවුන් කළමනාකරණය නොකළ සම්පත් කිහිපයක් කාන්දු වනු ඇත !

සටහන: ඒවා කළමණාකරන සම්පත් කාන්දු නොකරනු ඇත , මන්ද අවසානයේදී කසළ එකතු කරන්නා පසුබිම් නූල් මත ධාවනය වන අතර භාවිතයට නොගත් ඕනෑම වස්තුවක් සමඟ සම්බන්ධිත මතකය නිදහස් කරයි. මෙයට ඔබේ වස්තුව සහ ඔබ භාවිතා කරන ඕනෑම කළමනාකරණ වස්තු ඇතුළත් වේ (උදා: Bitmapසහ. DbConnection).

පුද්ගලයාට ඇමතීමට අමතක වූවා නම් Dispose(), අපට තවමත් ඔවුන්ගේ බේකන් ඉතිරි කළ හැකිය ! ඔවුන් සඳහා එය කැඳවීමට අපට තවමත් ක්‍රමයක් තිබේ : කසළ එකතු කරන්නා අවසානයේ අපගේ වස්තුව නිදහස් කිරීමට (එනම් අවසන් කිරීමට) ගිය විට.

සටහන: කසළ එකතු කරන්නා අවසානයේ කළමනාකරණය කරන ලද සියලුම වස්තු නිදහස් කරයි. එය සිදු වූ විට, එය Finalize වස්තුව මත ඇති ක්‍රමය අමතයි . ඔබේ බැහැර කිරීමේ ක්‍රමය ගැන GC දන්නේ නැත . කළමනාකරණය නොකළ දේවල් ඉවත් කිරීමට අවශ්‍ය විට අප අමතන ක්‍රමයක් සඳහා අප තෝරාගත් නමක් පමණි.

කසළ එකතු කරන්නා විසින් අපගේ වස්තුව විනාශ කිරීම එම කරදරකාරී කළමනාකරණය නොකළ සම්පත් නිදහස් කිරීමට සුදුසුම කාලයයි. අපි මෙය කරන්නේ Finalize()ක්‍රමවේදය ඉක්මවා යාමෙනි .

සටහන: C # හි, ඔබ පැහැදිලිවම Finalize()ක්‍රමය ඉක්මවා යන්නේ නැත . ඔබ ක්රමයක් ලියන්න වගේ එය C ++ destructor , සහ සම්පාදක බව ඔබේ ක්රියාත්මක කිරීම සඳහා අවශ්ය කරන්නේ Finalize()ක්රමය:

~MyObject()
{
    //we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
    Dispose(); //<--Warning: subtle bug! Keep reading!
}

නමුත් එම කේතයේ දෝෂයක් තිබේ. කසළ එකතු කරන්නා පසුබිම් නූල් මත ධාවනය වන බව ඔබට පෙනේ ; වස්තූන් දෙකක් විනාශ වන අනුපිළිවෙල ඔබ දන්නේ නැත. ඔබගේ Dispose()කේතයේ, ඔබ ඉවත් කිරීමට උත්සාහ කරන කළමනාකරණ වස්තුව (ඔබට උදව් කිරීමට අවශ්‍ය නිසා) තවදුරටත් එහි නොමැති බව සම්පුර්ණයෙන්ම විය හැකිය :

public void Dispose()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);

   //Free managed resources too
   if (this.databaseConnection != null)
   {
      this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
      this.databaseConnection = null;
   }
   if (this.frameBufferImage != null)
   {
      this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
      this.frameBufferImage = null;
   }
}

එබැවින් ඔබට අවශ්‍ය වන්නේ කළමනාකරණය නොකළ සම්පත් නිදහස් කරන අතරම එය කළමනාකරණය කළ සම්පත් කිසිවක් ස්පර්ශ නොකළ යුතු බව Finalize()පැවසීමට මාර්ගයකි (ඒවා තවදුරටත් එහි නොතිබිය හැකි නිසා ).Dispose()

මෙය සිදු කිරීම සඳහා සම්මත රටාව තිබිය යුතු Finalize()අතර Dispose()දෙදෙනාම තුන්වන (!) ක්‍රමයක් අමතන්න ; එහිදී ඔබ බූලියන් කියමින් එය අමතන්නේ නම් Dispose()(ඊට වෙනස්ව Finalize()), එයින් අදහස් කරන්නේ කළමනාකරණය කළ සම්පත් නිදහස් කිරීම ආරක්ෂිත බවයි.

මෙම අභ්‍යන්තර ක්‍රමයට “CoreDispose” හෝ “MyInternalDispose” වැනි අත්තනෝමතික නමක් ලබා දිය හැකි නමුත් එය හැඳින්වීම සම්ප්‍රදායයි Dispose(Boolean):

protected void Dispose(Boolean disposing)

නමුත් වඩාත් ප්‍රයෝජනවත් පරාමිති නාමයක් විය හැකිය:

protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //Free managed resources too, but only if I'm being called from Dispose
   //(If I'm being called from Finalize then the objects might not exist
   //anymore
   if (itIsSafeToAlsoFreeManagedObjects)  
   {    
      if (this.databaseConnection != null)
      {
         this.databaseConnection.Dispose();
         this.databaseConnection = null;
      }
      if (this.frameBufferImage != null)
      {
         this.frameBufferImage.Dispose();
         this.frameBufferImage = null;
      }
   }
}

ඔබ IDisposable.Dispose()ක්‍රමවේදය ක්‍රියාත්මක කිරීම වෙනස් කරන්නේ:

public void Dispose()
{
   Dispose(true); //I am calling you from Dispose, it's safe
}

සහ ඔබේ අවසන් කරන්නා:

~MyObject()
{
   Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}

සටහන : ඔබේ වස්තුව ක්‍රියාත්මක වන්නේ වස්තුවකින් නම් Dispose, ඔබ ඒවා ඉක්මවා යන විට ඒවායේ පදනම බැහැර කිරීමේ ක්‍රමය අමතන්න අමතක නොකරන්න .

public override void Dispose()
{
    try
    {
        Dispose(true); //true: safe to free managed resources
    }
    finally
    {
        base.Dispose();
    }
}

සියලු යහපත් ඔබ වඩා හොඳින් කළ හැකි හැර !


පරිශීලකයා Dispose()ඔබේ වස්තුව අමතන්නේ නම් , එවිට සියල්ල පිරිසිදු කර ඇත. පසුව, කසළ එකතු කරන්නා පැමිණ අවසන් කරන්නැයි ඇමතූ විට, එය Disposeනැවත අමතනු ඇත.

මෙය නාස්තියක් පමණක් නොව, ඔබේ වස්තුවට ඔබ අවසන් ඇමතුමේ සිට දැනටමත් බැහැර කර ඇති වස්තූන් පිළිබඳ අපැහැදිලි යොමු කිරීම් තිබේ නම් Dispose(), ඔබ ඒවා නැවත බැහැර කිරීමට උත්සාහ කරනු ඇත!

මගේ කේතයෙන් ඔබ දකිනු ඇත, මා විසින් බැහැර කරන ලද වස්තූන් පිළිබඳ යොමු කිරීම් ඉවත් කිරීමට මම ප්‍රවේශම් වූ බැවින් මම Disposeකුණු වස්තු යොමු කිරීමක් ඇමතීමට උත්සාහ නොකරමි . නමුත් එය සියුම් දෝෂයක් ඇතුළට යාම නතර කළේ නැත.

පරිශීලකයා ඇමතූ විට Dispose(): CursorFileBitmapIconServiceHandle හසුරුව විනාශ වේ. පසුව කසළ එකතු කරන්නා ධාවනය වන විට, එය නැවත එම හසුරුව විනාශ කිරීමට උත්සාහ කරනු ඇත.

protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy 
   ...
}

ඔබ මෙය නිවැරදි කරන ආකාරය කුණු එකතු කරන්නාට පවසන්න, එය වස්තුව අවසන් කිරීමට කරදර විය යුතු නැත - එහි සම්පත් දැනටමත් පිරිසිදු කර ඇති අතර තවත් වැඩක් අවශ්‍ය නොවේ. ඔබට ඇමතීම මගින් මේ GC.SuppressFinalize()තුළ Dispose()ක්රමය:

public void Dispose()
{
   Dispose(true); //I am calling you from Dispose, it's safe
   GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}

දැන් පරිශීලකයා ඇමතූ විට Dispose(), අපට ඇත්තේ:

  • කළමනාකරණය නොකළ සම්පත් නිදහස්
  • කළමනාකරණ සම්පත් නිදහස්

අවසන් මහා තරගය පවත්වාගෙන යාමේ කිසිදු තේරුමක් නැත - සෑම දෙයක්ම බලා ගනී.

කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම සඳහා මට අවසන් කිරීම භාවිතා කළ නොහැකිද?

සඳහා වන ලියකියවිලි Object.Finalizeමෙසේ කියයි:

වස්තුව විනාශ වීමට පෙර වත්මන් වස්තුව සතුව ඇති කළමනාකරණය නොකළ සම්පත් මත පිරිසිදු කිරීමේ මෙහෙයුම් සිදු කිරීම සඳහා අවසාන ක්‍රමය භාවිතා කරයි.

එම්එස්ඩීඑන් ලියකියවිලි ද මෙසේ කියයි IDisposable.Dispose:

කළමනාකරණය නොකළ සම්පත් නිදහස් කිරීම, මුදා හැරීම හෝ නැවත සැකසීම හා සම්බන්ධ යෙදුම්-නිර්වචනය කළ කාර්යයන් ඉටු කරයි.

ඉතින් එය කුමක්ද? කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීමට මට ඇති ස්ථානය කුමක්ද? පිළිතුර:

එය ඔබේ තේරීමයි! නමුත් තෝරන්න Dispose.

ඔබට කළමණාකරනය නොකළ පිරිසිදු කිරීම අවසාන කොටසේ තැබිය හැකිය.

~MyObject()
{
   //Free unmanaged resources
   Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);

   //A C# destructor automatically calls the destructor of its base class.
}

එහි ඇති ගැටළුව නම් කසළ එකතු කරන්නා ඔබේ වස්තුව අවසන් කරන්නේ කවදාද යන්න ගැන ඔබට කිසිම අදහසක් නැත. ඔබේ කළමනාකරණය නොකළ, අනවශ්‍ය, භාවිතයට නොගත් දේශීය සම්පත් කසළ එකතු කරන්නා අවසානයේදී ක්‍රියාත්මක වන තුරු රැඳී සිටියි. එවිට එය ඔබගේ අවසන් කිරීමේ ක්‍රමය අමතනු ඇත; කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම. Object.Finalize හි ප්‍රලේඛනය මෙය පෙන්වා දෙයි:

අවසන් කරන්නා ක්‍රියාත්මක කරන නිශ්චිත වේලාව නිර්වචනය කර නැත. ඔබේ පන්තියේ අවස්ථා සඳහා නිශ්චිතවම සම්පත් මුදා හැරීම සහතික කිරීම සඳහා, වසා දැමීමේ ක්‍රමයක් IDisposable.Disposeක්‍රියාත්මක කිරීම හෝ ක්‍රියාත්මක කිරීම සපයන්න .

Disposeකළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම සඳහා භාවිතා කිරීමේ ගුණාංගය මෙයයි ; කළමනාකරණය නොකළ සම්පත් පිරිසිදු කළ විට ඔබ දැන හඳුනා ගැනීම සහ පාලනය කිරීම. ඔවුන්ගේ විනාශය "නිර්ණායක" ය .


ඔබේ මුල් ප්‍රශ්නයට පිළිතුරු සැපයීම සඳහා: GC එය කිරීමට තීරණය කළ කාලයට වඩා දැන් මතකය නිදහස් නොකරන්නේ ඇයි? බව මට මුහුණේ පිළිගැනීමක් මෘදුකාංග අවශ්යතා අභ්යන්තර රූප 530 MB මිදෙන්නට දැන් ඔවුන් තවදුරටත් අවශ්ය කරන්නේ සිට. අප එසේ නොකරන විට: යන්ත්‍රය මාරු කිරීම නවත්වයි.

පාරිතෝෂික කියවීම

මෙම පිළිතුරේ ශෛලියට කැමති ඕනෑම අයෙකුට (එයට හේතුව පැහැදිලි කරන්නේ කෙසේද , එසේ වන්නේ කෙසේද යන්න පැහැදිලි කිරීම), මම ඔබට යෝජනා කරන්නේ දොන් බොක්ස් හි අත්‍යවශ්‍ය COM හි පළමු පරිච්ඡේදය කියවන්න:

පිටු 35 කින් ඔහු ද්විමය වස්තු භාවිතා කිරීමේ ගැටළු පැහැදිලි කරන අතර ඔබේ ඇස් ඉදිරිපිට COM නිර්මාණය කරයි. COM හි හේතුව ඔබ තේරුම් ගත් පසු , ඉතිරි පිටු 300 පැහැදිලිව පෙනෙන අතර මයික්‍රොසොෆ්ට් ක්‍රියාත්මක කිරීම පිළිබඳ විස්තරාත්මකව.

මම හිතන්නේ මෙතෙක් වස්තූන් හෝ COM සමඟ ගනුදෙනු කළ සෑම ක්‍රමලේඛකයෙක්ම අවම වශයෙන් පළමු පරිච්ඡේදය කියවිය යුතුය. එය ඕනෑම දෙයක හොඳම පැහැදිලි කිරීමයි.

අමතර බෝනස් කියවීම

එරික් ලිපර්ට් විසින් ඔබ දන්නා සියල්ල වැරදියි

එබැවින් නිවැරදි අවසන් ලේඛනයක් ලිවීම ඇත්තෙන්ම ඉතා අපහසු වන අතර , මම ඔබට දිය හැකි හොඳම උපදෙස් වන්නේ උත්සාහ නොකිරීමයි .


14
ඔබට වඩා හොඳින් කළ හැකිය - ඔබ බැහැර කිරීමේදී GC.SuppressFinalize () වෙත ඇමතුමක් එක් කළ යුතුය.
plinth

55
An ඩැනියෙල් අර්විකර්: ඒක ඇත්ත. වින් 32 භාවිතා කිරීම මුළුමනින්ම නැවැත්වීමට මයික්‍රොසොෆ්ට් ඔබට ප්‍රිය කරයි. ඔබට යටින් ඇති මෙහෙයුම් පද්ධතිය වටා ගමන් කිරීමට අවශ්‍ය නම්; ඔබ නිසා හිතන්න ඔබ ඔබේ ම අතට ඔබේ ජීවිතය අරන් යන්නේ: ඔබ මෙහෙයුම් පද්ධතිය ධාවනය වන දේ දන්නවා. සෑම .NET යෙදුමක්ම වින්ඩෝස් හෝ ඩෙස්ක්ටොප් එකක ක්‍රියාත්මක නොවේ.
ඉයන් බොයිඩ්

34
මෙය හොඳ පිළිතුරක් වන නමුත් සම්මත නඩුවක් සඳහා වන අවසාන කේත ලැයිස්තුගත කිරීමකින් සහ පන්තිය ව්‍යුත්පන්න කර ඇති බේස් ක්ලාස් එකකින් ලබා ගන්නා අවස්ථාවකට කෙසේ වෙතත් එය ප්‍රයෝජනවත් වනු ඇතැයි මම සිතමි. උදා: මෙහි කියවීමකින් ( msdn.microsoft.com/en-us/library/aa720161%28v=vs.71%29.aspx ) මෙන්ම මම දැනටමත් ඉවත් ක්රියාත්මක කරන (පන්ති සහ ජනතාවට විට කළ යුතු දේ ගැන ව්යාකූල වී ඇත හේයි මම මේකට අලුත්).
integra753

5
Reg ග්‍රෙග්ස් සහ වෙනත් අය: සාමාන්‍යයෙන් මම යොමු කිරීම් ගැන කරදර නොවෙමි null. පළමුවෙන්ම, එයින් අදහස් කරන්නේ ඔබට ඒවා සෑදිය නොහැකි බවත් readonly, දෙවනුව, ඔබ ඉතා කැත !=nullචෙක්පත් කළ යුතු බවත්ය (උදාහරණ කේතයේ මෙන්). ඔබට ධජයක් තිබිය හැකි disposedනමුත් ඒ ගැන කරදර නොවීම පහසුය. .NET GC ආක්‍රමණශීලී වන අතර එය ක්ෂේත්‍රයක් පිළිබඳ සඳහනක් රේඛාව පසු xකරන විට තවදුරටත් 'භාවිතා' කරනු නොලැබේ x.Dispose().
porges

7
ඔබ සඳහන් කළ දොන් බොක්ස් පොතේ දෙවන පිටුවේ, ඔහු සෙවුම් ඇල්ගොරිතම ක්‍රියාත්මක කිරීම පිළිබඳ උදාහරණය භාවිතා කරයි, එහි විස්තර “පා er කයාට අභ්‍යාසයක් ලෙස ඉතිරිව ඇත”. මම හිනා වුණා.
පිස දමන්න

66

IDisposableබොහෝ විට භාවිතා කරනුයේ usingප්‍රකාශය ගසාකෑමට සහ කළමනාකරණ වස්තූන් නිර්ණය ලෙස පිරිසිදු කිරීම සඳහා පහසු ක්‍රමයකින් ප්‍රයෝජන ගැනීමට ය.

public class LoggingContext : IDisposable {
    public Finicky(string name) {
        Log.Write("Entering Log Context {0}", name);
        Log.Indent();
    }
    public void Dispose() {
        Log.Outdent();
    }

    public static void Main() {
        Log.Write("Some initial stuff.");
        try {
            using(new LoggingContext()) {
                Log.Write("Some stuff inside the context.");
                throw new Exception();
            }
        } catch {
            Log.Write("Man, that was a heavy exception caught from inside a child logging context!");
        } finally {
            Log.Write("Some final stuff.");
        }
    }
}

6
මම පෞද්ගලිකව එයට කැමතියි, නමුත් එය සැබවින්ම රාමු සැලසුම් මාර්ගෝපදේශ සමඟ නොගැලපේ.
mqp

4
මම එය නිසි සැලසුමක් ලෙස සලකන්නේ එය පහසුවෙන් නිර්ණය කළ හැකි විෂය පථයන් සහ විෂය පථ ඉදිකිරීම් / පිරිසිදු කිරීම් වලට ඉඩ සලසන බැවිනි. භාෂාව මෙය පළමු පන්තියේ අංගයක් ලෙස ඉදිරිපත් කරයි.
yfeldblum

එය එෆ්ඩීජී හි නිශ්චිතව දක්වා ඇති නීති රීති හරියටම අනුගමනය නොකරන නමුත් එය නිසැකවම "භාවිතා කරන ප්‍රකාශය" භාවිතා කිරීම සඳහා අවශ්‍ය රටාවේ වලංගු භාවිතයකි.
ස්කොට් ඩෝර්මන්

2
Log.Outdent විසි නොකරන තාක් කල්, මෙහි කිසිඳු වරදක් නොමැත.
ඩැනියෙල් අර්විකර්

1
විවිධාකාර පිළිතුරු ව්‍යතිරේක ආරක්ෂාව සඳහා “විෂය පථය” ලබා ගැනීමේ මාධ්‍යයක් ලෙස හඳුනාගත නොහැකි සහ “භාවිතා කිරීම” අනිසි ලෙස භාවිතා කරන්නේද? විවිධ පුද්ගලයින් මෙම තාක්ෂණයට කැමති / අකමැති වීමට හේතුව ගැන තව ටිකක් විස්තරාත්මකව බලන්න. එය තරමක් මතභේදාත්මක ය.
බ්‍රයන්

45

බැහැර කිරීමේ රටාවේ පරමාර්ථය වන්නේ කළමනාකරණය කරන ලද සහ කළමනාකරණය නොකරන ලද සම්පත් පිරිසිදු කිරීම සඳහා යාන්ත්‍රණයක් සැපයීමයි. එය සිදු වූ විට එය බැහැර කිරීමේ ක්‍රමය හඳුන්වන්නේ කෙසේද යන්න මත රඳා පවතී. ඔබේ උදාහරණයේ දී, බැහැර කිරීම භාවිතා කිරීම ඇත්ත වශයෙන්ම බැහැර කිරීම හා සම්බන්ධ කිසිවක් නොකරයි, මන්ද ලැයිස්තුවක් ඉවත් කිරීමෙන් එම එකතුව බැහැර කිරීමට කිසිදු බලපෑමක් නැත. ඒ හා සමානව, විචල්යයන් ශුන්ය ලෙස සැකසීමේ ඇමතුම් ද GC කෙරෙහි කිසිදු බලපෑමක් ඇති නොකරයි.

බැහැර කිරීමේ රටාව ක්‍රියාත්මක කරන්නේ කෙසේද යන්න පිළිබඳ වැඩි විස්තර සඳහා ඔබට මෙම ලිපිය දෙස බැලිය හැකිය , නමුත් එය මූලික වශයෙන් මේ ආකාරයෙන් පෙනේ:

public class SimpleCleanup : IDisposable
{
    // some fields that require cleanup
    private SafeHandle handle;
    private bool disposed = false; // to detect redundant calls

    public SimpleCleanup()
    {
        this.handle = /*...*/;
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                if (handle != null)
                {
                    handle.Dispose();
                }
            }

            // Dispose unmanaged managed resources.

            disposed = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

මෙහි වඩාත්ම වැදගත් ක්‍රමය වන්නේ බැහැර කිරීම (බූල්) ය, එය සැබවින්ම වෙනස් තත්වයන් දෙකක් යටතේ ක්‍රියාත්මක වේ:

  • dispizing == true: මෙම ක්‍රමය පරිශීලක කේතයක් මගින් සෘජුව හෝ වක්‍රව කැඳවා ඇත. කළමනාකරණය කළ හා කළමනාකරණය නොකළ සම්පත් බැහැර කළ හැකිය.
  • බැහැර කිරීම == අසත්ය: ක්රමවේදය ධාවන කාලය විසින් අවසන් කරන්නාගේ ඇතුළත සිට කැඳවා ඇති අතර ඔබ වෙනත් වස්තු සඳහන් නොකළ යුතුය. කළමනාකරණය කළ නොහැකි සම්පත් පමණක් බැහැර කළ හැකිය.

පිරිසිදු කිරීම පිළිබඳ සැලකිලිමත් වීමට GC ට ඉඩ දීමේ ගැටළුව නම්, GC විසින් එකතු කිරීමේ චක්‍රයක් ක්‍රියාත්මක කරන්නේ කවදාද යන්න පිළිබඳව ඔබට සැබෑ පාලනයක් නොමැති වීමයි (ඔබට GC.Collect () අමතන්න, නමුත් ඔබ එසේ නොකළ යුතුය) එබැවින් සම්පත් පවතිනු ඇත අවශ්‍ය ප්‍රමාණයට වඩා දිගු. මතක තබා ගන්න, ඩිස්පෝස් () ඇමතීමෙන් ඇත්ත වශයෙන්ම එකතු කිරීමේ චක්‍රයක් ඇති නොවන අතර කිසිම ආකාරයකින් ජීසී විසින් වස්තුව එකතු කිරීමට / නිදහස් කිරීමට හේතු නොවේ; එය හුදෙක් භාවිතා කරන සම්පත් වඩාත් නිර්ණායක ලෙස පිරිසිදු කිරීමට මාධ්‍යයන් සපයන අතර මෙම පිරිසිදු කිරීම දැනටමත් සිදු කර ඇති බව GC වෙත පවසන්න.

IDisposable සහ බැහැර කිරීමේ රටාවේ සමස්ත ලක්ෂ්‍යය වහාම මතකය නිදහස් කිරීම නොවේ. බැහැර කිරීම සඳහා වූ ඇමතුමකට ඇත්ත වශයෙන්ම මතකය ක්ෂණිකව නිදහස් කර ගැනීමට අවස්ථාවක් ඇති එකම අවස්ථාව වන්නේ එය බැහැර කිරීම == ව්‍යාජ අවස්ථා සහ කළමනාකරණය නොකළ සම්පත් හැසිරවීමේදී ය. කළමණාකරන කේතය සඳහා, GC එකතු කිරීමේ චක්‍රයක් ක්‍රියාත්මක කරන තෙක් මතකය නැවත ලබා නොගනු ඇත, එය ඔබට ඇත්ත වශයෙන්ම පාලනය කළ නොහැක (GC.Collect () ඇමතීම හැර, මම දැනටමත් සඳහන් කර ඇති හොඳ අදහසක් නොවේ).

.NET හි ඇති නූල් කිසිදු හානියක් නොකළ සම්පත් භාවිතා නොකරන අතර IDisposable ක්‍රියාත්මක නොකරන්න, ඒවා "පිරිසිදු කිරීමට" බල කිරීමට ක්‍රමයක් නොමැත.


4
අවසාන ක්‍රියාවට නැංවීමට ඔබට අමතක වූයේ නැද්ද?
බුද්ධ

Ud බුඩා: නැත, ඔහු භාවිතා කරන්නේ සේෆ්හැන්ඩල් ය. විනාශ කරන්නෙකුගේ අවශ්‍යතාවයක් නැත.
හෙන්ක් හෝල්ටර්මන්

9
විසුරුවා හැරීම () වෙත බහු ඇමතුම් සඳහා ආරක්ෂිත දැලක් එක් කිරීම සඳහා +1. පිරිවිතර පවසන්නේ බහු ඇමතුම් ආරක්ෂිත විය යුතු බවයි. බොහෝ මයික්‍රොසොෆ්ට් පංති එය ක්‍රියාත්මක කිරීමට අපොහොසත් වන අතර ඔබට කරදරකාරී ObjectDisposedException ලැබෙනු ඇත.
ජෙසී චිෂොල්ම්

5
විසුරුවා හැරීම (බූල් බැහැර කිරීම) ඔබේ සරල ක්ලීනප් පන්තියේ ඔබේම ක්‍රමයක් වන අතර එය කිසි විටෙකත් රාමුවෙන් කැඳවනු නොලැබේ. ඔබ එය "සත්‍ය" සමඟ පරාමිතියක් ලෙස පමණක් හඳුන්වන බැවින්, 'බැහැර කිරීම' කිසි විටෙකත් අසත්‍ය නොවේ. ඔබේ කේතය IDisposable සඳහා වන MSDN උදාහරණයට බොහෝ සෙයින් සමාන ය, නමුත් ud බුඩා පෙන්වා දුන් පරිදි, අවසාන කාරකය නොමැති වීම, බැහැර කිරීම = අසත්‍යය සහිත ඇමතුම එන්නේ එතැනිනි.
යෝයෝ

19

ඩිස්පෝස් කැඳවීමෙන් පසු වස්තුවක ක්‍රමවේදයන්ට තවදුරටත් ඇමතුම් නොතිබිය යුතුය (වස්තුවක් බැහැර කිරීම සඳහා තවදුරටත් ඇමතුම් නොඉවසිය යුතුය). එබැවින් ප්රශ්නයේ උදාහරණය මෝඩය. විසුරුවා හැරීම නම්, එම වස්තුවම ඉවත දැමිය හැකිය. එබැවින් පරිශීලකයා එම සම්පූර්ණ වස්තුව පිළිබඳ සියලු යොමු කිරීම් ඉවත දැමිය යුතුය (ඒවා ශුන්‍ය ලෙස සකසන්න) එවිට එයට අභ්‍යන්තරව ඇති සියලුම වස්තු ස්වයංක්‍රීයව පිරිසිදු වේ.

කළමනාකරණය කළ / කළමනාකරණය නොකළ පොදු ප්‍රශ්නය සහ වෙනත් පිළිතුරු වල සාකච්ඡාව සම්බන්ධයෙන් ගත් කල, මෙම ප්‍රශ්නයට ඕනෑම පිළිතුරක් කළමනාකරණය නොකළ සම්පතක් පිළිබඳ අර්ථ දැක්වීමකින් ආරම්භ කළ යුතු යැයි මම සිතමි.

එය තම්බා ඇති දෙය නම් පද්ධතිය තත්වයට පත් කිරීම සඳහා ඔබට ඇමතිය හැකි ශ්‍රිතයක් ඇති අතර එය නැවත එම තත්වයෙන් පිටතට ගෙන ඒම සඳහා ඔබට ඇමතිය හැකි තවත් ශ්‍රිතයක් ඇත. දැන්, සාමාන්‍ය උදාහරණයේ දී, පළමුවැන්න ගොනු හසුරුව නැවත ලබා දෙන ශ්‍රිතයක් විය හැකි අතර දෙවැන්න ඇමතුමක් විය හැකිය CloseHandle.

නමුත් - සහ මෙය යතුරයි - ඒවා ගැලපෙන ඕනෑම ශ්‍රිත යුගලයක් විය හැකිය. එක් අයෙක් රාජ්‍යයක් ගොඩනඟයි, අනෙකා එය කඳුළු සලයි. රාජ්‍යය ඉදිකර ඇති නමුත් තවමත් කඩා දමා නොමැති නම්, සම්පත පිළිබඳ උදාහරණයක් පවතී. කඳුළු ගැලීම නියමිත වේලාවට සිදුවීමට ඔබ කටයුතු කළ යුතුය - සම්පත කළමනාකරණය කරන්නේ සීඑල්ආර් විසිනි. ස්වයංක්‍රීයව කළමනාකරණය කළ හැකි එකම සම්පත් වර්ගය මතකයයි. වර්ග දෙකක් තිබේ: ජීසී සහ තොගය. අගය වර්ග කළමනාකරණය කරනු ලබන්නේ තොගයෙනි (නැතහොත් විමර්ශන වර්ග ඇතුළත ගමනක් යාමෙන්), සහ විමර්ශන වර්ග කළමනාකරණය කරනු ලබන්නේ ජී.සී.

මෙම කාර්යයන් නිදහසේ අන්තර් සම්බන්ධිත විය හැකි රාජ්‍ය වෙනස්කම් වලට හේතු විය හැකිය, නැතහොත් පරිපූර්ණව කැදැල්ලට අවශ්‍ය විය හැකිය. රාජ්ය වෙනස්වීම් නූල් ආරක්ෂිත විය හැකිය, නැතහොත් එසේ නොවිය හැකිය.

විනිසුරුගේ ප්‍රශ්නයේ උදාහරණය දෙස බලන්න. ලොග් ගොනුවේ ඉන්ඩෙන්ටේෂන් හි වෙනස්කම් පරිපූර්ණ ලෙස කූඩු කළ යුතුය, නැතහොත් ඒ සියල්ල වැරදී යයි. එසේම ඒවා නූල් ආරක්ෂිත විය නොහැක.

ඔබේ කළමනාකරණය නොකළ සම්පත් පිරිසිදු කර ගැනීම සඳහා කසළ එකතු කරන්නා සමඟ ගමනක් යා හැකිය. නමුත් රාජ්‍ය වෙනස් කිරීමේ කාර්යයන් නූල් ආරක්ෂිත නම් සහ ප්‍රාන්ත දෙකකට ඕනෑම ආකාරයකින් අතිච්ඡාදනය වන ජීවිත කාලය තිබිය හැකිය. එබැවින් සම්පතක් පිළිබඳ යුක්තියේ ආදර්ශයට අවසාන කාරකයක් නොතිබිය යුතුය! එය කිසිවෙකුට උදව් නොකරනු ඇත.

එම සම්පත් සඳහා, ඔබට IDisposableඅවසන් කරන්නෙකු නොමැතිව ක්‍රියාත්මක කළ හැකිය . අවසාන කාරකය අත්‍යවශ්‍ය නොවේ - එය එසේ විය යුතුය. මෙය බොහෝ ග්‍රන්ථවල සඳහන් කර නැත.

එවිට ඔබ එම usingප්‍රකාශය භාවිතා කර Disposeඑය කැඳවනු ලැබීමට වග බලා ගත යුතුය. මෙය අත්‍යාවශ්‍යයෙන්ම තොගය සමඟ ගමනක් යෑමට සමාන ය (අවසාන නිමැවුම ජී.සී.ට මෙන්ම, තොගයට ද usingවේ).

අස්ථානගත වී ඇති කොටස නම්, ඔබ විසින් අතින් ලිවිය යුතු අතර එය ඔබේ ක්ෂේත්‍රයට සහ ඔබේ මූලික පන්තියට ඇමතිය යුතුය. C ++ / CLI ක්‍රමලේඛකයන්ට එය කිරීමට අවශ්‍ය නැත. සම්පාදකයා එය බොහෝ විට ඔවුන් සඳහා ලියයි.

විකල්පයක් ඇත, එය වඩාත් සුදුසු වන්නේ කූඩුව හා නූල් ආරක්ෂිත නොවන රාජ්‍යයන් සඳහා ය. .

පංතියක් ලිවීම වෙනුවට ඔබ ශ්‍රිතයක් ලියයි. නැවත ඇමතීම සඳහා ශ්‍රිතය නියෝජිතයෙකු පිළිගනී:

public static void Indented(this Log log, Action action)
{
    log.Indent();
    try
    {
        action();
    }
    finally
    {
        log.Outdent();
    }
}

එවිට සරල උදාහරණයක් වනු ඇත:

Log.Write("Message at the top");
Log.Indented(() =>
{
    Log.Write("And this is indented");

    Log.Indented(() =>
    {
        Log.Write("This is even more indented");
    });
});
Log.Write("Back at the outermost level again");

ලැම්බඩාව සම්මත කර ඇත්තේ කේත වාරණයක් ලෙසය using, එම නිසා ඇමතුම්කරු එය අනිසි ලෙස භාවිතා කිරීමේ අවදානමක් ඔබට නොමැති බව හැර, එකම අරමුණක් ඉටු කිරීම සඳහා ඔබ ඔබේම පාලන ව්‍යුහයක් සාදන්නාක් මෙනි . සම්පත පිරිසිදු කිරීමට ඔවුන්ට අසමත් විය හැකි ක්‍රමයක් නොමැත.

සම්පත ජීවිත කාලය ඉක්මවා යා හැකි ආකාරයේ නම් මෙම තාක්ෂණය අඩු ප්‍රයෝජනවත් නොවේ, මන්ද එවිට ඔබට අවශ්‍ය වන්නේ සම්පත් A, පසුව සම්පත් B, පසුව සම්පත් A kill ාතනය කර පසුව සම්පත් විනාශ කිරීමයි. ඔබට එය කළ නොහැක ඔබ මේ ආකාරයට පරිපූර්ණ ලෙස කූඩු කිරීමට පරිශීලකයාට බල කර ඇත්නම්. නමුත් පසුව ඔබ භාවිතා කළ යුතුය IDisposable(නමුත් තවමත් අවසන් කිරීමකින් තොරව, ඔබ නූල් සුරක්‍ෂිතතාවය ක්‍රියාත්මක කර ඇත්නම් මිස එය නොමිලේ නොවේ).


re: "වස්තුවක් විසුරුවා හැරීමෙන් පසුව එය තවදුරටත් ඇමතීම නොකළ යුතුය". ක්‍රියාකාරී වචනය වීම “විය යුතුය”. ඔබට අසමමුහුර්ත ක්‍රියා ඉතිරිව තිබේ නම්, ඒවා ඔබේ වස්තුව බැහැර කිරීමෙන් පසුව පැමිණිය හැකිය. ObjectDisposedException ඇති කිරීම.
ජෙසී චිෂොල්ම්

කළමනාකරණය නොකළ සම්පත්, ග්‍රාම නිලධාරීවරයාට නොතේරෙන තත්වයක් ආවරණය කරයි යන අදහස ස්පර්ශ කරන මගේ හැර වෙනත් පිළිතුර ඔබේ බව පෙනේ. කෙසේ වෙතත්, කළමනාකරණය නොකරන ලද සම්පතක ප්‍රධාන අංගයක් නම්, රාජ්‍යයට පිරිසිදු කිරීම අවශ්‍ය විය හැකි ආයතන එකක් හෝ වැඩි ගණනක් සම්පත “අයිති” වස්තුව නොතිබුණත් දිගටම පැවතිය හැකි වීමයි. ඔබ මගේ අර්ථ දැක්වීමට කැමති වන්නේ කෙසේද? බෙහෙවින් සමාන ය, නමුත් මම සිතන්නේ එය "සම්පත" තව ටිකක් නාම පදයක් බවට පත් කරයි (එහි සේවාවන් තවදුරටත් අවශ්‍ය නොවන විට දැනුම් දීම සඳහා හුවමාරුවක් වශයෙන් එහි හැසිරීම වෙනස් කිරීම සඳහා බාහිර වස්තුව විසින් කරන ලද "ගිවිසුම")
සුපර් කැට්

up සුපර්කැට් - ඔබ කැමති නම් මම ඉහත පිළිතුර ලිවීමෙන්
ඩැනියෙල්

1
An ඩැනියෙල් එර්විකර්: සිත්ගන්නාසුලු ලිපිය, ඔබ සැබවින්ම ආවරණය නොකරන අවම වශයෙන් එක් ආකාරයක කළමණාකරනය නොකළ සම්පතක් ගැන මට සිතිය හැකි වුවද: දිගුකාලීන වස්තූන්ගෙන් සිදුවීම් සඳහා දායකත්වය. සිදුවීම් දායකත්වයන් දිලීර, නමුත් මතකය අසීමිත වුවද ඒවා බැහැර කිරීමට අපොහොසත් වීම මිල අධික විය හැකිය. නිදසුනක් ලෙස, ගණනය කිරීමේදී වෙනස් කිරීමට ඉඩ දෙන එකතුවක් සඳහා ගණන් ගන්නෙකුට එකතුවෙන් දැනුම්දීම් යාවත්කාලීන කිරීමට දායක වීමට අවශ්‍ය විය හැකි අතර එකතුවක් එහි ජීවිත කාලය තුළ බොහෝ වාරයක් යාවත්කාලීන කළ හැකිය. ගණන් නොගෙන ගණනය කිරීම් අතහැර
දැමුවහොත්

1
මෙහෙයුම් යුගලය enterසහ exitමම සම්පතක් ගැන සිතන ආකාරයෙහි හරය වේ. සිදුවීම් සඳහා දායකත්වය / දායකත්වය ලබා ගැනීම අපහසුතාවයකින් තොරව එයට ගැලපේ. විකලාංග / දිලීර ලක්ෂණ අනුව එය ප්‍රායෝගිකව මතක කාන්දුවකින් වෙන් කොට හඳුනාගත නොහැකිය. (දායකත්වය ලැයිස්තුවකට වස්තු එකතු කිරීම නිසා මෙය පුදුමයට කරුණක් නොවේ.)
ඩැනියෙල් අර්විකර්

17

අවස්ථා මම හඳුනාගත නොහැකි ලෙස භාවිතා කරමි: කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීම, සිදුවීම් සඳහා දායක නොවීම, සමීප සම්බන්ධතා

IDisposable ( නූල් ආරක්ෂිත නොවේ ) ක්‍රියාත්මක කිරීම සඳහා මා භාවිතා කරන මෝඩකම :

class MyClass : IDisposable {
    // ...

    #region IDisposable Members and Helpers
    private bool disposed = false;

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing) {
        if (!this.disposed) {
            if (disposing) {
                // cleanup code goes here
            }
            disposed = true;
        }
    }

    ~MyClass() {
        Dispose(false);
    }
    #endregion
}

සම්පූර්ණ රටා පැහැදිලි කිරීම msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
LicenseQ

3
ඔබට කළමනාකරණය නොකළ සම්පත් නොමැති නම් කිසි විටෙකත් අවසන් කරන්නෙකු ඇතුළත් නොකළ යුතුය. එසේ වුවද, වඩාත් සුදුසු ක්‍රියාත්මක කිරීම වන්නේ කළමනාකරණය නොකළ සම්පත SafeHandle හි ආවරණය කිරීමයි.
ඩේව් බ්ලැක්

11

ඔව්, එම කේතය මුළුමනින්ම අතිරික්ත හා අනවශ්‍ය වන අතර එය කසළ එකතු කරන්නා වෙනත් ආකාරයකින් නොකරන කිසිවක් නොකරයි (MyCollection හි උදාහරණයක් විෂය පථයෙන් බැහැර වූ පසු, එනම්.) විශේෂයෙන් .Clear()ඇමතුම්.

ඔබගේ සංස්කරණයට පිළිතුර: වර්ග කිරීම. මම මෙය කරන්නේ නම්:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has no Dispose() method
    instance.FillItWithAMillionStrings();
}

// 1 million strings are in memory, but marked for reclamation by the GC

මතක කළමනාකරණ අරමුණු සඳහා එය ක්‍රියාකාරීව සමාන වේ:

public void WasteMemory()
{
    var instance = new MyCollection(); // this one has your Dispose()
    instance.FillItWithAMillionStrings();
    instance.Dispose();
}

// 1 million strings are in memory, but marked for reclamation by the GC

ඔබට මේ මොහොතේම මතකය නිදහස් කිරීමට සැබවින්ම අවශ්‍ය නම්, අමතන්න GC.Collect(). මෙහි මෙය කිරීමට හේතුවක් නැත. අවශ්‍ය විටදී මතකය නිදහස් වේ.


2
re: "අවශ්‍ය විටදී මතකය නිදහස් වේ." ඒ වෙනුවට කියන්න, "GC තීරණය කළ විට එය අවශ්‍යයි." මතකය සැබවින්ම අවශ්‍ය බව GC තීරණය කිරීමට පෙර ඔබට පද්ධති ක්‍රියාකාරිත්වයේ ගැටළු දැකිය හැකිය . දැන් එය නිදහස් කිරීම අත්‍යවශ්‍ය නොවිය හැකි නමුත් ප්‍රයෝජනවත් විය හැකිය.
ජෙසී චිෂොල්ම්

1
එකතුවක් තුළ යොමු කිරීම් අහෝසි කිරීමෙන් එමඟින් යොමු කරන ලද අයිතමවල කසළ එකතු කිරීම වේගවත් කළ හැකි සමහර අවස්ථා තිබේ. නිදසුනක් ලෙස, විශාල අරාවක් නිර්මාණය කර කුඩා අලුතින් සාදන ලද අයිතම සඳහා යොමු කිරීම් වලින් පිරී තිබේ නම්, නමුත් එය බොහෝ කලකට පසුව අවශ්‍ය නොවන්නේ නම්, අරාව අතහැර දැමීමෙන් ඊළඟ මට්ටමේ 2 GC තෙක් එම අයිතම තබා ගත හැකිය, පළමුවෙන්ම එය ශුන්‍ය කිරීම මඟින් ඊළඟ මට්ටමේ 0 හෝ 1 මට්ටමේ GC සඳහා අයිතම සුදුසුකම් ලබයි. ඇත්ත වශයෙන්ම, විශාල වස්තු සංචයේ විශාල කෙටිකාලීන වස්තූන් තිබීම කෙසේ වෙතත් අමිහිරි ය (මම සැලසුමට
අකමැතියි

1
... එවැනි අරා අතහැර දැමීමට පෙර ශුන්‍ය කිරීම මගේ සමහර විට GC බලපෑම අඩු කරයි.
සුපර්කැට්

11

MyCollectionකෙසේ හෝ කසළ එකතු කිරීමට යන්නේ නම් , ඔබ එය බැහැර කිරීමට අවශ්‍ය නොවිය යුතුය. එසේ කිරීමෙන් අවශ්‍ය ප්‍රමාණයට වඩා CPU අවුල් වන අතර කසළ එකතු කරන්නා දැනටමත් සිදු කර ඇති පූර්ව ගණනය කළ විශ්ලේෂණයක් පවා අවලංගු කරයි.

IDisposableකළමනාකරණය නොකළ සම්පත් සමඟ නූල් නිවැරදිව බැහැර කිරීම සහතික කිරීම වැනි දේවල් කිරීමට මම භාවිතා කරමි .

සංස්කරණය කරන්න ස්කොට්ගේ ප්‍රකාශයට ප්‍රතිචාර වශයෙන්:

[Sic] GC.Collect () ඇමතුමක් ලබා ගත් විට GC කාර්ය සාධන ප්‍රමිතිකයට බලපාන එකම අවස්ථාව මෙයයි.

සංකල්පමය වශයෙන්, GC විසින් වස්තු යොමු ප්‍රස්ථාරය පිළිබඳ දර්ශනයක් පවත්වා ගෙන යන අතර, ඒ පිළිබඳ සියලු යොමු කිරීම් නූල්වල රාමු වලින් ලබා ගනී. මෙම සංචය තරමක් විශාල විය හැකි අතර මතක පිටු රාශියක් විහිදේ. ප්‍රශස්තිකරණයක් ලෙස, අනවශ්‍ය ලෙස පිටුව නැවත ලබා ගැනීම වළක්වා ගැනීම සඳහා බොහෝ විට වෙනස් විය නොහැකි පිටු පිළිබඳ විශ්ලේෂණය GC විසින් රඳවා ගනී. පිටුවක දත්ත වෙනස් වන විට GC හට කර්නලයෙන් දැනුම් දීමක් ලැබෙනු ඇත, එම නිසා පිටුව අපිරිසිදු බවත් එය නැවත සකස් කිරීමක් අවශ්‍ය බවත් එය දනී. එකතුව Gen0 හි තිබේ නම්, පිටුවේ වෙනත් දේවල් ද වෙනස් වීමට ඉඩ ඇත, නමුත් මෙය Gen1 සහ Gen2 හි අඩු ඉඩක් ඇත. එම වේදිකාවේ සිල්වර් ලයිට් ප්ලග් ඉන් වැඩ කිරීම සඳහා GC මැක් වෙත වරාය කළ කණ්ඩායම සඳහා මැක් ඕඑස් එක්ස් හි මෙම කොකු නොතිබුණි.

සම්පත් අනවශ්‍ය ලෙස බැහැර කිරීමට එරෙහි තවත් කරුණක්: ක්‍රියාවලියක් මුදා හරින තත්වයක් ගැන සිතන්න. මෙම ක්‍රියාවලිය කලක සිට ක්‍රියාත්මක වන බව සිතන්න. එම ක්‍රියාවලියේ බොහෝ මතක පිටු තැටියට මාරු කර ඇති අවස්ථා තිබේ. අවම වශයෙන් ඒවා තවදුරටත් L1 හෝ L2 හැඹිලියේ නොමැත. එවැනි තත්වයක් තුළ, ක්‍රියාවලිය අවසන් වූ විට කෙසේ හෝ මෙහෙයුම් පද්ධතිය විසින් මුදා හැරීමට යන සම්පත් 'මුදා හැරීම' සඳහා එම සියලු දත්ත සහ කේත පිටු නැවත මතකය වෙත මාරු කිරීමට යෙදුමට කිසිදු තේරුමක් නැත. කළමනාකරණය කළ සහ කළමනාකරණය නොකළ ඇතැම් සම්පත් සඳහා මෙය අදාළ වේ. පසුබිම් නොවන නූල් පණපිටින් තබා ගත හැකි සම්පත් පමණක් බැහැර කළ යුතුය, එසේ නොමැති නම් ක්‍රියාවලිය සජීවීව පවතිනු ඇත.

දැන්, සාමාන්‍ය ක්‍රියාත්මක කිරීමේදී පාලනය නොකළ මතක කාන්දුවීම් වලක්වා ගැනීම සඳහා නිවැරදිව පිරිසිදු කළ යුතු අත්‍යවශ්‍ය සම්පත් තිබේ (zfezmonkey දත්ත සමුදා සම්බන්ධතා, සොකට්, කවුළු හසුරුවන පරිදි ). බැහැර කළ යුතු දේවල් මේවාය. ඔබ නූල් හිමිකාරීත්වයක් ඇති යම් පංතියක් නිර්මාණය කරන්නේ නම් (සහ එය මා විසින් එය නිර්මාණය කළ බවත්, එබැවින් එය අවම වශයෙන් මගේ කේතීකරණ ශෛලිය අනුව නතර වන බව සහතික කිරීමේ වගකීම දරයි), එවිට එම පන්තිය බොහෝ විට ක්‍රියාත්මක විය යුතු IDisposableඅතර නූල් ඉරා දැමිය යුතුය Dispose.

.NET රාමුව මඟින් IDisposableමෙම පන්තිය බැහැර කළ යුතු බවට සංවර්ධකයින්ට අනතුරු ඇඟවීමක් පවා සං signal ාවක් ලෙස අතුරු මුහුණත භාවිතා කරයි . IDisposableබැහැර කිරීම විකල්පයක් වන (පැහැදිලි අතුරුමුහුණත් ක්‍රියාත්මක කිරීම හැර) ක්‍රියාත්මක කරන රාමුවේ කිසිදු වර්ගයක් ගැන මට සිතිය නොහැක .


ඩිස්පෝස් කිරීම ඇමතීම සම්පූර්ණයෙන්ම වලංගු, නීතිමය සහ දිරිමත් වේ. IDisposable ක්‍රියාත්මක කරන වස්තු සාමාන්‍යයෙන් එසේ කරන්නේ හේතුවක් නිසාය. GC කාර්ය සාධන ප්‍රමිතිකයට බලපාන එකම අවස්ථාව වන්නේ GC.Collect () ඇමතුමක් ලබා ගත් විට පමණි.
ස්කොට් ඩෝර්මන්

බොහෝ .net පංති සඳහා, බැහැර කිරීම “තරමක්” විකල්පයක් වන අතර, එයින් අදහස් වන්නේ “සාමාන්‍යයෙන්” සිද්ධීන් අතහැර දැමීම නව අවස්ථා නිර්මාණය කිරීම සහ ඒවා අතහැර දැමීම පිස්සු වැටෙන්නේ නැති තාක් කල් කිසිදු කරදරයක් ඇති නොවන බවයි. නිදසුනක් ලෙස, පාලකයන් සඳහා සම්පාදක ජනනය කළ කේතය මඟින් පාලනයන් ක්ෂණිකව ක්‍රියාත්මක වන විට අකුරු නිර්මාණය වන අතර ආකෘති බැහැර කරන විට ඒවා අතහැර දමයි. යමෙක් දහස් ගණනක් පාලනයන් නිර්මාණය කර බැහැර කරන්නේ නම්, මෙය GDI හසුරුවීම් දහස් ගණනක් ගැටගැසීමට ඉඩ ඇත, නමුත් බොහෝ අවස්ථාවන්හිදී පාලනයන් එතරම්ම නිර්මාණය වී විනාශ නොවේ. එසේ වුවද, එවැනි අත්හැරීම වළක්වා ගැනීමට යමෙකු තවමත් උත්සාහ කළ යුතුය.
සුපර් කැට්

1
අකුරු සම්බන්ධයෙන් ගත් කල, ගැටලුව වන්නේ පාලනයකට පවරා ඇති “අකුරු” වස්තුව බැහැර කිරීම සඳහා වගකිව යුතු ආයතනය කුමක්දැයි මයික්‍රොසොෆ්ට් කිසි විටෙකත් නිර්වචනය කර නොමැති බව මම සැක කරමි; සමහර අවස්ථාවලදී, පාලකයන් විසින් දිගු කාලයක් පවතින වස්තුවක් සමඟ අකුරු බෙදා ගත හැක, එබැවින් පාලනයක් තිබීම අකුරු විසුරුවා හැරීම නරක වනු ඇත. වෙනත් අවස්ථාවල දී, පාලනයක් සඳහා අකුරු වර්ගයක් පවරනු ලබන අතර වෙන කොතැනකවත් නැත, එබැවින් පාලනය එය බැහැර නොකරන්නේ නම් කිසිවෙකු එසේ නොකරනු ඇත. අහම්බෙන්, වෙනම ඉවත දැමිය නොහැකි ෆොන්ට් ටෙම්ප්ලේට් පංතියක් තිබුනේ නම්, අකුරු සමඟ ඇති මෙම දුෂ්කරතාවය මඟහරවා ගත හැකි විය, මන්ද පාලකයන් ඔවුන්ගේ අකුරු වල ජීඩීඅයි හසුරුව භාවිතා කරන බවක් නොපෙනේ.
සුපර් කැට්

විකල්ප Dispose()ඇමතුම් පිළිබඳ මාතෘකාව මත , බලන්න: stackoverflow.com/questions/913228/…
RJ Cuthbertson

7

ඔබ පළ කළ උදාහරණයේ, එය තවමත් "මතකය දැන් නිදහස් නොකරයි". සියලුම මතකය කසළ එකතු කර ඇති නමුත් එය පෙර පරම්පරාවක මතකය එකතු කිරීමට ඉඩ සලසයි . ඔබට නිසැකවම පරීක්ෂණ කිහිපයක් ක්‍රියාත්මක කිරීමට සිදුවේ.


රාමු සැලසුම් මාර්ගෝපදේශ යනු මාර්ගෝපදේශ මිස නීති නොවේ. අතුරු මුහුණත මූලික වශයෙන් කුමක් සඳහාද, එය භාවිතා කළ යුත්තේ කවදාද, එය භාවිතා කරන්නේ කෙසේද සහ එය භාවිතා නොකළ යුත්තේ කවදාද යන්න ඔවුන් ඔබට කියයි.

IDisposable භාවිතා කිරීම අසමත් වීම පිළිබඳ සරල රෝල්බැක් () කේතයක් මම වරක් කියෙව්වෙමි. පහත දැක්වෙන මිනිටීඑක්ස් පන්තිය ඩිස්පෝස් () හි ධජයක් පරික්ෂා කරන අතර Commitඇමතුම කිසි විටෙකත් සිදු නොවූයේ නම් Rollbackඑය තමාටම කියා ගනී. එය ඇමතුම් කේතය තේරුම් ගැනීමට සහ නඩත්තු කිරීමට පහසු කරවන පරිදි අවිනිශ්චිත තට්ටුවක් එක් කළේය. ප්‍රති result ලය වගේ දෙයක් පෙනුණා:

using( MiniTx tx = new MiniTx() )
{
    // code that might not work.

    tx.Commit();
} 

වේලාව / ල ging ු-සටහන් කේතය එකම දේ කරන බව මම දැක ඇත්තෙමි. මෙම අවස්ථාවේ දී විසුරුවා හැරීමේ () ක්‍රමය මඟින් ටයිමරය නැවැත්වූ අතර බ්ලොක් එක පිටවී ඇති බව සටහන් විය.

using( LogTimer log = new LogTimer("MyCategory", "Some message") )
{
    // code to time...
}

එබැවින් කළමනාකරණය නොකළ සම්පත් පිරිසිදු කිරීමක් නොකරන කොන්ක්‍රීට් උදාහරණ කිහිපයක් මෙන්න, නමුත් පිරිසිදු කේතයක් නිර්මාණය කිරීම සඳහා IDisposable සාර්ථකව භාවිතා කරන්න.


ඉහළ ඇණවුම් කාර්යයන් භාවිතා කරමින් ඩැනියෙල් අර්විකර්ගේ උදාහරණය දෙස බලන්න. මිණුම් සලකුණු කිරීම, වේලාව, ලොග් වීම යනාදිය සඳහා එය වඩාත් සරල බව පෙනේ.
අළුආන් හඩාඩ්


6

කළමනාකරණය නොකළ සම්පත් භාවිතා කිරීම හෝ නිදහස් කිරීම පිළිබඳ සුපුරුදු දේවල් මම නැවත නොකියමි. නමුත් පොදු වැරදි වැටහීමක් ලෙස පෙනෙන දේ පෙන්වා දීමට මම කැමතියි.
පහත කේතය ලබා දී ඇත

පොදු පන්තියේ විශාල දේවල්
  හඳුනාගත නොහැකි ලෙස ක්‍රියාත්මක කරයි
  පුද්ගලික _ විශාල නූලක් ලෙස ()

  _ලාර්ජ් හි සමහර අමුතු කේත වල දැන් දිගු නූල් මිලියන කිහිපයක් අඩංගු වේ.

  පොදු උප බැහැර කිරීම () IDisposable.Dispose ක්‍රියාත්මක කරයි
    _ලාර්ජ් = කිසිවක් නැත
  අවසන් උප

ඉවත දැමිය හැකි ක්‍රියාත්මක කිරීම වර්තමාන මාර්ගෝපදේශ අනුගමනය නොකරන බව මම තේරුම් ගතිමි, නමුත් ඔබ සැමට අදහස ලැබෙනු ඇතැයි බලාපොරොත්තු වෙමු.
දැන්, ඩිස්පෝස් කැඳවූ විට, මතකය කොපමණ ප්‍රමාණයක් නිදහස් වේද?

පිළිතුර: නැත.
ඩිස්පෝස් ඇමතීමෙන් කළමනාකරණය නොකළ සම්පත් නිදහස් කළ හැකිය, එය කළමණාකරන මතකය නැවත ලබා ගත නොහැක, එය කළ හැක්කේ GC ට පමණි. ඉහත සඳහන් දේ හොඳ අදහසක් නොවන බව නොකියයි, ඉහත රටාව අනුගමනය කිරීම ඇත්ත වශයෙන්ම හොඳ අදහසකි. ඩිස්පෝස් ධාවනය කළ පසු, ලාර්ජ් ස්ටෆ් හි උදාහරණය තවමත් විෂය පථයේ පැවතිය හැකි වුවද, _ලාර්ජ් විසින් භාවිතා කරන ලද මතකය නැවත ලබා ගැනීම සඳහා ජී.සී. _Large හි ඇති නූල් ද gen 0 විය හැකි නමුත් LargeStuff හි උදාහරණය gen 2 විය හැකිය, එබැවින් නැවතත් මතකය ඉක්මනින් නැවත ලබා ගත හැක.
ඉහත පෙන්වා ඇති විසුරුවා හැරීමේ ක්‍රමය ඇමතීමට අවසන් කාරකයක් එකතු කිරීමෙන් පලක් නැත. එමඟින් අවසන් මතකය ක්‍රියාත්මක කිරීමට ඉඩ දීම සඳහා මතකය නැවත ප්‍රකාශ කිරීම ප්‍රමාද වනු ඇත.


1
නිදසුනක් LargeStuff2 වන පරම්පරාවට ගෙන ඒමට තරම් දිගු කාලයක් ගත වී ඇත්නම් සහ _Largeපරම්පරාවේ 0 හි ඇති අළුතින් සාදන ලද නූලක් ගැන සඳහනක් තිබේ නම්, එම අවස්ථාව LargeStuffඅහෝසි නොකර අතහැර දමනු ලැබුවහොත් _Large, _Largeඊළඟ Gen2 එකතුව තෙක් තබා ඇත. පිටතට Zeroing _Largeවැල ඉදිරි Gen0 එකතුව දී ඉවත් කර ගැනීමට ඉඩ සැලසිය හැක. බොහෝ අවස්ථාවන්හීදී, යොමු කිරීම් අහෝසි කිරීම ප්‍රයෝජනවත් නොවේ, නමුත් එයින් යම් ප්‍රතිලාභයක් ලබා ගත හැකි අවස්ථා තිබේ.
සුපර් කැට්

5

මීට අමතරව පාලනය කිරීමට ක්රමයක් ලෙස එහි ප්රාථමික භාවිතය සිට ජීවිත කාලය වන පද්ධති සම්පත් (සම්පූර්ණයෙන්ම දීපු පිළිතුර මගින් ආවරණය ඉයන් !, සුවිශේෂී සම්මානය), එම IDisposable / භාවිතා combo ද භාවිතා කළ හැක විෂය පථය (තීරණාත්මක) ගෝලීය සම්පත් රාජ්ය වෙනස් : මෙම කොන්සෝලය , එම නූල් , එම ක්රියාවලිය , ඕනෑම ගෝලීය වස්තුව ක වැනි අයදුම් උදාහරණයක් .

මම මෙම රටාව ගැන ලිපියක් ලියා ඇත: http://pragmateek.com/c-scope-your-global-state-changes-with-idisposable-and-the-using-statement/

නැවත භාවිතා කළ හැකි සහ කියවිය හැකි ආකාරයකින් බොහෝ විට භාවිතා කරන ගෝලීය තත්වය ඔබට ආරක්ෂා කළ හැකි ආකාරය එය නිරූපණය කරයි : කොන්සෝල වර්ණ , වත්මන් නූල් සංස්කෘතිය , එක්සෙල් යෙදුම් වස්තු ගුණාංග ...


4

ඕනෑම දෙයක් නම්, කේතය පිටවන විට වඩා කාර්යක්ෂමතාව අඩු වනු ඇතැයි මම අපේක්ෂා කරමි .

පැහැදිලි () ක්‍රම ඇමතීම අනවශ්‍ය වන අතර, බැහැර කිරීම සිදු නොකළේ නම් GC බොහෝ විට එසේ නොකරනු ඇත ...


2

බව දේවල් තියෙනවා Dispose()ඒ මෙහෙයුම ආදර්ශය කේතය ඒක කරන්නේ හැකි පිළිබඳ සාමාන්ය GC නිසා ඇති නොවන බව බලපෑමක් ඇති MyCollectionවස්තුවක්.

වෙනත් වස්තූන් විසින් යොමු කරන ලද _theListහෝ _theDictයොමු කරන ලද වස්තූන් නම්, එම List<>හෝ Dictionary<>වස්තුව එකතු කිරීමට යටත් නොවන නමුත් හදිසියේම එහි අන්තර්ගතයක් නොමැත. උදාහරණයේ දී මෙන් බැහැර කිරීමේ () මෙහෙයුමක් නොතිබුනේ නම්, එම එකතුවෙහි ඒවායේ අන්තර්ගතය තවමත් අඩංගු වේ.

ඇත්තෙන්ම, මම මේ බිඳුණු නිර්මාණය යනුවෙන් හැඳින්විය හැකි තත්ත්වය නම් - මම මේ බව පෙන්වා දෙමින් ඉන්නවා (pedantically, මම හිතන්නේ) Dispose()මෙහෙයුම සඳහා අනෙකුත් භාවිතා තිබේද මත පදනම්ව, සම්පූර්ණයෙන්ම අතිරික්ත විය නොහැකි විය List<>හෝ Dictionary<>බව නොවේ කැබැල්ලේ පෙන්වා ඇත.


ඒවා පෞද්ගලික ක්ෂේත්‍රයන් වන අතර, එබැවින් OP ඔවුන් වෙත යොමු කිරීම් ලබා නොදේ යැයි සිතීම සාධාරණ යැයි මම සිතමි.
mqp

1) කේත කැබැල්ල උදාහරණ කේතය පමණි, එබැවින් මම පෙන්වා දෙන්නේ නොසලකා හැරීමට පහසු අතුරු ආබාධයක් තිබිය හැකි බවයි; 2) පුද්ගලික ක්ෂේත්‍ර බොහෝ විට ලබන්නාගේ දේපල / ක්‍රමයේ ඉලක්කය වේ - සමහර විට ඕනෑවට වඩා වැඩියි (සමහර අය විසින් ලබා ගන්නා / සකසන අය ටිකක් රටා විරෝධී යැයි සලකනු ලැබේ).
මයිකල් බර්

2

“කළමනාකරණය නොකළ සම්පත්” පිළිබඳ බොහෝ සාකච්ඡාවල ඇති එක් ගැටළුවක් නම්, ඔවුන් එම පදය සැබවින්ම නිර්වචනය නොකිරීම, නමුත් එය කළමනාකරණය නොකළ කේත සමඟ යම් සම්බන්ධයක් ඇති බව අඟවයි. බොහෝ කළමණාකරනය නොකළ සම්පත් කළමනාකරණය නොකළ කේත සමඟ අන්තර් ක්‍රියා කරන බව සත්‍යයක් වන අතර, කළමනාකරණය නොකළ සම්පත් එවැනි වචනවලින් සිතීම ප්‍රයෝජනවත් නොවේ.

ඒ වෙනුවට, කළමණාකරන සම්පත් සියල්ලටම පොදු දේ යමෙක් හඳුනාගත යුතුය: ඒ සියල්ලටම යම් දෙයක් 'පිටත' යම් දෙයක් ඉල්ලා සිටිමින් ඒ වෙනුවෙන් යමක් කිරීමට, වෙනත් 'දේවල්' වලට හානි කිරීමට, අනෙක් ආයතනය එසේ කිරීමට එකඟ වන තෙක් වැඩිදුර දැනුම්දීම. හෝඩුවාවක් නොමැතිව වස්තුව අතහැර දමා අතුරුදහන් වුවහොත්, තවදුරටත් නොපවතින වස්තුව වෙනුවෙන් එහි හැසිරීම වෙනස් කිරීමට තවදුරටත් අවශ්‍ය නොවන බව පිටත 'දෙයක්' කිසි විටෙකත් නොකියනු ඇත; එහි ප්‍රති, ලයක් වශයෙන්, 'දේවල ප්‍රයෝජනය ස්ථිරවම හීන වනු ඇත.

කළමනාකරණය නොකරන ලද සම්පතක්, එසේ නම්, යම් වස්තුවක් වෙනුවෙන් එහි හැසිරීම වෙනස් කිරීම සඳහා බාහිර 'යම් දෙයක්' විසින් කරන ලද ගිවිසුමක් නිරූපණය කරයි, එමඟින් එම වස්තුව අතහැර දමා පැවතීම නතර වුවහොත් එම බාහිර 'දේ' වල ප්‍රයෝජනය නිෂ් less ල වනු ඇත. කළමනාකරණ සම්පතක් යනු එවැනි ගිවිසුමක ප්‍රතිලාභියා වන වස්තුවකි, නමුත් එය අතහැර දැමුවහොත් දැනුම්දීම ලබා ගැනීම සඳහා අත්සන් තබා ඇති අතර එය විනාශ වීමට පෙර එහි කටයුතු පිළිවෙලට තැබීමට එවැනි දැනුම්දීමක් භාවිතා කරනු ඇත.


හොඳයි, IMO, කළමනාකරණය නොකළ වස්තුව පිළිබඳ අර්ථ දැක්වීම පැහැදිලිය; GC නොවන ඕනෑම වස්තුවක් .
eonil

1
OnEonil: කළමනාකරණය නොකළ වස්තුව! = කළමනාකරණය නොකළ සම්පත්. සිදුවීම් වැනි දේවල් මුළුමනින්ම කළමනාකරණය කළ වස්තූන් භාවිතයෙන් ක්‍රියාත්මක කළ හැකි නමුත් තවමත් කළමනාකරණය නොකළ සම්පත් වලින් සමන්විත වේ - අවම වශයෙන් දිගු කාලීන වස්තූන්ගේ සිදුවීම් සඳහා දායක වන කෙටි කාලීන වස්තූන් සම්බන්ධයෙන් වුවද - ඒවා පිරිසිදු කරන්නේ කෙසේද යන්න පිළිබඳව GC කිසිවක් දන්නේ නැත. .
සුපර් කැට්


2

පළමු අර්ථ දැක්වීම. මට කළමනාකරණය නොකළ සම්පතක් යනු කිසියම් පන්තියක් වන අතර එය හඳුනාගත නොහැකි අතුරු මුහුණතක් හෝ ඩීඑල් වෙත ඇමතුම් භාවිතා කිරීමෙන් නිර්මාණය කරන ලද යමක් ක්‍රියාත්මක කරයි. එවැනි වස්තූන් සමඟ කටයුතු කරන්නේ කෙසේදැයි GC නොදනී. උදාහරණයක් ලෙස පන්තියට ඇත්තේ වටිනාකම් වර්ග පමණක් නම්, මම මෙම පන්තිය කළමනාකරණය නොකළ සම්පත් සහිත පන්තියක් ලෙස නොසිතමි. මගේ කේතය සඳහා මම ඊළඟ භාවිතයන් අනුගමනය කරමි:

  1. මා විසින් නිර්මාණය කරන ලද පංතිය කළමනාකරණය නොකළ සම්පත් කිහිපයක් භාවිතා කරයි නම් එයින් අදහස් වන්නේ මතකය පිරිසිදු කිරීම සඳහා IDisposable අතුරුමුහුණත ද ක්‍රියාත්මක කළ යුතු බවයි.
  2. මම එය භාවිතා කළ වහාම වස්තු පිරිසිදු කරන්න.
  3. මගේ බැහැර කිරීමේ ක්‍රමයේදී මම පන්තියේ සියලුම හඳුනාගත නොහැකි සාමාජිකයන් ගැන නැවත කියමි.
  4. මගේ බැහැර කිරීමේ ක්‍රමයේදී GC.SuppressFinalize (මෙය) අමතන්න, මගේ වස්තුව දැනටමත් පිරිසිදු කර ඇති බව කසළ එකතු කරන්නාට දැනුම් දීම. මම එය කරන්නේ GC ඇමතීම මිල අධික මෙහෙයුමක් වන බැවිනි.
  5. අතිරේක පූර්වාරක්ෂාවක් ලෙස මම ඩිස්පෝස් () ඇමතීමට කිහිප වතාවක්ම උත්සාහ කරමි.
  6. සමහර වෙලාවට මම පුද්ගලික සාමාජිකයෙක් එකතු කර _ ඇමතුම් පරීක්ෂා කර බැලුවෙමි. එය පිරිසිදු කර ඇත්නම් ObjectDisposedException ජනනය කරන්න
    පහත අච්චුව මඟින් වචන වලින් මා විස්තර කර ඇත්තේ කේතයේ නියැදියක් ලෙස ය:

public class SomeClass : IDisposable
    {
        /// <summary>
        /// As usually I don't care was object disposed or not
        /// </summary>
        public void SomeMethod()
        {
            if (_disposed)
                throw new ObjectDisposedException("SomeClass instance been disposed");
        }

        public void Dispose()
        {
            Dispose(true);
        }

        private bool _disposed;

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;
            if (disposing)//we are in the first call
            {
            }
            _disposed = true;
        }
    }

1
"මට කළමනාකරණය නොකළ සම්පතක් යනු කිසියම් පන්තියක් වන අතර එය හඳුනාගත නොහැකි අතුරු මුහුණතක් හෝ ඩීඑල් වෙත ඇමතුම් භාවිතයෙන් නිර්මාණය කරන ලද යමක් ක්‍රියාත්මක කරයි." ඉතින් ඔබ කියන්නේ is IDisposableකළමනාකරණය නොකළ සම්පතක් ලෙස සැලකිය යුතු ඕනෑම වර්ගයක් ? එය නිවැරදි බවක් නොපෙනේ. එසේම implmenting වර්ගය පිරිසිදු අගය වර්ගයක් නම් එය බැහැර කිරීම අවශ්‍ය නොවන බව ඔබ යෝජනා කරයි. එය ද වැරදිය.
අලුවාන් හඩාඩ්

සෑම කෙනෙකුම තනිවම විනිශ්චය කරයි. එකතු කිරීම සඳහා මගේ කේතයට යමක් එකතු කිරීමට මා කැමති නැත. එහි අර්ථය වන්නේ මම IDisposable එකතු කළහොත්, එයින් අදහස් වන්නේ GC හට කළමනාකරණය කළ නොහැකි යම් ආකාරයක ක්‍රියාකාරිත්වයක් මා විසින් නිර්මාණය කර ඇති බවයි හෝ එහි ආයු කාලය නිසි ලෙස කළමනාකරණය කිරීමට එයට නොහැකි වනු ඇතැයි මම සිතමි.
යූරි සාලෙට්ස්කි

2

ඔබ ලබා දී ඇති කේත නියැදිය IDisposableභාවිතය සඳහා හොඳ උදාහරණයක් නොවේ . ශබ්දකෝෂ නිශ්කාෂණය සාමාන්‍යයෙන්Dispose ක්‍රමයට නොයා යුතුය . ශබ්ද කෝෂ අයිතමයන් විෂය පථයෙන් බැහැර වූ විට ඉවත් කර බැහැර කරනු ලැබේ. IDisposableසමහර මතක / හසුරුවන්නන් නිදහස් කිරීමට / ක්‍රියාත්මක කිරීමට අවශ්‍ය වේ.

පහත දැක්වෙන උදාහරණයෙන් සමහර කේත සහ අදහස් සහිත IDisposable රටාව සඳහා හොඳ උදාහරණයක් පෙන්වයි.

public class DisposeExample
{
    // A base class that implements IDisposable. 
    // By implementing IDisposable, you are announcing that 
    // instances of this type allocate scarce resources. 
    public class MyResource: IDisposable
    {
        // Pointer to an external unmanaged resource. 
        private IntPtr handle;
        // Other managed resource this class uses. 
        private Component component = new Component();
        // Track whether Dispose has been called. 
        private bool disposed = false;

        // The class constructor. 
        public MyResource(IntPtr handle)
        {
            this.handle = handle;
        }

        // Implement IDisposable. 
        // Do not make this method virtual. 
        // A derived class should not be able to override this method. 
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method. 
            // Therefore, you should call GC.SupressFinalize to 
            // take this object off the finalization queue 
            // and prevent finalization code for this object 
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios. 
        // If disposing equals true, the method has been called directly 
        // or indirectly by a user's code. Managed and unmanaged resources 
        // can be disposed. 
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed. 
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called. 
            if(!this.disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources. 
                if(disposing)
                {
                    // Dispose managed resources.
                    component.Dispose();
                }

                // Call the appropriate methods to clean up 
                // unmanaged resources here. 
                // If disposing is false, 
                // only the following code is executed.
                CloseHandle(handle);
                handle = IntPtr.Zero;

                // Note disposing has been done.
                disposed = true;

            }
        }

        // Use interop to call the method necessary 
        // to clean up the unmanaged resource.
        [System.Runtime.InteropServices.DllImport("Kernel32")]
        private extern static Boolean CloseHandle(IntPtr handle);

        // Use C# destructor syntax for finalization code. 
        // This destructor will run only if the Dispose method 
        // does not get called. 
        // It gives your base class the opportunity to finalize. 
        // Do not provide destructors in types derived from this class.
        ~MyResource()
        {
            // Do not re-create Dispose clean-up code here. 
            // Calling Dispose(false) is optimal in terms of 
            // readability and maintainability.
            Dispose(false);
        }
    }
    public static void Main()
    {
        // Insert code here to create 
        // and use the MyResource object.
    }
}

1

කළමනාකරණ සම්පත් බැහැර කිරීම සඳහා වඩාත්ම යුක්ති සහගත භාවිත අවස්ථාව නම්, කිසි විටෙකත් එකතු නොකරන සම්පත් නැවත ලබා ගැනීමට GC සූදානම් වීමයි.

ප්‍රධාන උදාහරණයක් වන්නේ රවුම් යොමු කිරීම් ය.

චක්‍රලේඛ යොමු කිරීම් වලක්වන රටා භාවිතා කිරීම වඩාත් හොඳ පුරුද්දක් වන අතර, ඔබ (නිදසුනක් ලෙස) 'ළමා' වස්තුවක් එහි 'මාපිය' වෙත යොමු කිරීමක් සමඟ අවසන් කරන්නේ නම්, ඔබ අතහැර දැමුවහොත් මවුපියන්ගේ ජී.සී. යොමු කිරීම සහ GC - ප්ලස් මත විශ්වාසය තබන්න ඔබ අවසන් යන්ත්‍රයක් ක්‍රියාත්මක කර ඇත්නම් එය කිසි විටෙකත් කැඳවනු නොලැබේ.

මේ සඳහා ඇති එකම ක්‍රමය නම්, දෙමාපියන්ගේ යොමු කිරීම් ළමයින්ට අහෝසි කිරීම සඳහා චක්‍රලේඛ යොමු කිරීම අතින් බිඳ දැමීමයි.

මෙය කළ හැකි හොඳම ක්‍රමය දෙමව්පියන් සහ දරුවන් මත හඳුනාගත නොහැකි ලෙස ක්‍රියාත්මක කිරීමයි. දෙමව්පියන්ට බැහැර කිරීම කැඳවූ විට, සියලු ළමයින් මත විසුරුවා හරින්න, සහ ළමා විසුරුවා හැරීමේ ක්‍රමයේදී, දෙමාපිය යොමු කිරීම් ශුන්‍ය ලෙස සකසන්න.


4
බොහෝ දුරට, GC වැඩ කරන්නේ මියගිය වස්තූන් හඳුනා ගැනීමෙන් නොව සජීවී ඒවා හඳුනා ගැනීමෙන් ය. එක් එක් ජීසී චක්‍රයට පසුව, අවසන් කිරීම සඳහා ලියාපදිංචි වී ඇති සෑම වස්තුවක්ම විශාල වස්තු ගොඩවල් මත ගබඩා කර ඇත, නැතහොත් සජීවී ඉලක්කයක් වේ නම් WeakReference, පද්ධතිය විසින් ධජයක් පරික්ෂා කරනු ඇත, එයින් පෙන්නුම් කරන්නේ සජීවී මුල් බැසගත් සඳහනක් පසුගිය ජීසී චක්‍රයේ තිබී ඇති බවයි. , සහ එක්කෝ වස්තුව ක්ෂණිකව අවසන් කිරීමට අවශ්‍ය වස්තු පෝලිම්වලට එකතු කිරීම, විශාල වස්තු සංචයෙන් වස්තුව මුදා හැරීම හෝ දුර්වල යොමුව අවලංගු කිරීම. චක්‍රලේඛ යොමු මඟින් වෙනත් යොමු කිරීම් නොමැති නම් වස්තූන් පණපිටින් තබා නොගනී.
සුපර් කැට්

1

කළමනාකරණ සහ කළමනාකරණය නොකළ සම්පත් සඳහා IDisposable භාවිතා කිරීම ගැන කතා කිරීමට බොහෝ පිළිතුරු මාරු වී ඇති බව මට පෙනේ. IDisposable සැබවින්ම භාවිතා කළ යුතු ආකාරය සඳහා මා සොයාගත් හොඳම පැහැදිලි කිරීමක් ලෙස මම මෙම ලිපිය යෝජනා කරමි.

https://www.codeproject.com/Articles/29534/IDisposable-What-Your-Mother-Never-Told-You-About

සත්‍ය ප්‍රශ්නය සඳහා; බොහෝ මතක ශක්තියක් ඇති කළමණාකරන වස්තු පිරිසිදු කිරීම සඳහා ඔබ IDisposable භාවිතා කරන්නේ නම් කෙටි පිළිතුර නැත . හේතුව, ඔබ හැඳුනුම්පතක් බැහැර කළ පසු එය විෂය පථයෙන් බැහැර වීමට ඉඩ දිය යුතුය. එම අවස්ථාවෙහිදී, යොමු කරන ලද ළමා වස්තූන් ද විෂය පථයෙන් බැහැර වන අතර ඒවා එකතු කරනු ලැබේ.

මෙයට ඇති එකම සැබෑ ව්‍යතිරේකය වනුයේ කළමනාකරණ වස්තූන් තුළ ඔබට විශාල මතක ප්‍රමාණයක් බැඳී ඇති අතර යම් මෙහෙයුමක් අවසන් වන තෙක් ඔබ එම නූල අවහිර කර තිබීමයි. එම ඇමතුම සම්පුර්ණ වූ පසු අවශ්‍ය නොවන වස්තූන් එම යොමු අහෝසි කිරීමෙන් කුණු එකතු කරන්නාට ඉක්මනින් ඒවා එකතු කර ගත හැකිය. නමුත් එම තත්වය නිරූපණය කරන්නේ ප්‍රතිනිර්මාණය කළ යුතු නරක කේතයක් මිස හඳුනාගත නොහැකි භාවිතයක් නොවේ.


1
ඔබේ පිළිතුරට කවුරුහරි -1 ක් දැමුවේ ඇයිදැයි මට තේරුණේ නැත
සෙබස්තියන් ඔස්කාර් ලෝපෙස්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.