Happy boxing day!

Tomáš Holan       26. 12. 2013       C#       5231 zobrazení

struct MyHandle : IDisposable
{
    private int Handle;
    internal bool IsDisposed { get; private set; }
    public MyHandle(int handle) : this() { this.Handle = handle; }
    private void CloseHandle() { ... }
    public void Dispose()
    {
        if (!this.IsDisposed)
        {
            CloseHandle();
            this.IsDisposed = true;
        }
    }
}

var resource = new MyHandle(123);
try
{
    //...
}
finally
{
    ((IDisposable)resource).Dispose();
}

Debug.Assert(resource.IsDisposed);

Vidíte kde je v uvedeném kódu chyba a proč?

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

Boxing day

Já jsem z toho vykoumal tolik, že zde:

((IDisposable)resource).Dispose();

se provádí boxing z hodnotového typu (struktura) na object. A protože je object v tomto případě (zde už si nejsem tak jistý) immutable, neboli neměnný, tak se vnitřní změny hodnot neprojeví a při unboxingu zůstane IsDisposed na defaultní hodnotě false.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Druhá část malinko nepřesně, ale jinak v zásadě správně.

Na uvedeném řádku přetypováním na interface opravdu dojde k operaci boxing (malá nápověda v nadpisu článku), tj. k vytvoření kopie dat hodnotového typu do nového objektu.

Metoda Dispose je pak volána nad touto kopií nikoliv nad původní hodnotou a tudíž pouze v této kopii dojde ke změně příznaku IsDisposed na true.

resource.IsDisposed zůstává false (což by v reálném scénáři nezabránilo použít již zavřený zdroj).

Problém je právě v tom, že tento hodnotový typ není immutable, a kód demonstruje obecnou špatnost "mutable" struktur, více jsem o tom v minulosti již psal zde:

http://www.dotnetportal.cz/blogy/15/Null...

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Ono je hlavně blbost používat IDisposable strukturu s nespravovanou pamětí. Navíc to rozhraní není ani správně implementované (destruktor apod.).

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To je příklad speciálně vykonstruován pro tu chybu s boxingem, dělat to takto v praxi je samozřejmě úplně špatně.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

Příspěvky zaslané pod tento článek se neobjeví hned, ale až po schválení administrátorem.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback