2013-03-01 20 views
6

To nie jest tak ważne, ale próbuję dowiedzieć się, co mi mówi i czy jest to uzasadnione ostrzeżenie? Czy ktoś może mi wyjaśnić ten błąd w prostych słowach?CA1001 Ostrzeżenie Visual Studio 2012 Analiza kodu. Co to znaczy?

CA1001 Rodzaje jednorazowych, które są właścicielami pól powinny być jednorazowe

Wdrożenie IDisposable na 'MemVoteManager', ponieważ tworzy członków o IDisposable następujących typów: 'CongressDBEntities. Jeśli wcześniej dostarczono "MemVoteManager" , dodawanie nowych członków, które implementują IDisposable do tego typu, jest uważane za przełomową zmianę w stosunku do istniejących konsumentów .

public class MemVoteManager : AbstractDataManager, IMemVoteManager 
{ 
    private CongressDBEntities context = new CongressDBEntities(); 

    public int AddMemVote(tMemVoteScore mvs) 
    { 
     //Insert Model 
     context.tMemVoteScores.Add(mvs); 
     context.SaveChanges(); 

     int newPK = mvs.MemVoteScoresID; 

     //Update funky column ID with PK as well 
     var memVoteItem = (from m in context.tMemVoteScores 
          where m.MemVoteScoresID == newPK 
          select m).SingleOrDefault(); 

     memVoteItem.ID = memVoteItem.MemVoteScoresID; 
     context.SaveChanges(); 
     return newPK; 
    } 
+3

Trudno będzie wyjaśnić, co to ostrzeżenie mówi, aby zrobić bez powtarzania ostrzeżenia. Ponieważ twój typ ma pole, w którym konstruuje obiekt i przechowuje do niego, gdzie ten obiekt implementuje IDisposable, powinieneś zaimplementować IDisposable również na swoim typie, usuwając obiekt w tym polu. Tak właściwie brzmi ostrzeżenie. Część z podziałem na zmiany polega na tym, że żaden istniejący kod, który używa twojego typu, nie zostałby zbudowany z myślą o "Rozmieszczaniu", a tym samym o przełomowej zmianie. –

Odpowiedz

7

Ty mógłby wdrożyć IDisposable więc kontekst będą usuwane kiedy konsumenci skończą z twoją klasą, ale możesz być lepiej NIE mając kontekstu być członkiem klasy. Wystarczy utworzyć go, gdy jest to potrzebne i rozporządzania nim, kiedy skończysz:

public int AddMemVote(tMemVoteScore mvs) 
{ 
    //Insert Model 
    using(CongressDBEntities context = new CongressDBEntities()) 
    { 
     context.tMemVoteScores.Add(mvs); 
     context.SaveChanges(); 

     int newPK = mvs.MemVoteScoresID; 

     //Update funky column ID with PK as well 
     var memVoteItem = (from m in context.tMemVoteScores 
          where m.MemVoteScoresID == newPK 
          select m).SingleOrDefault(); 

     memVoteItem.ID = memVoteItem.MemVoteScoresID; 
     context.SaveChanges(); 
    } 
    return newPK; 
} 

Konteksty są lekkie, więc nie jest to ogromne kary za tworzenie ich za każdym razem. Poza tym nie musisz się martwić o to, że konsumenci powiadamiają Cię, że musisz pozbyć się kontekstu, i nie masz zbyt wielu nagromadzonych zmian w pamięci, jeśli jedna instancja klasy jest używana wiele razy.

+0

Ale myślałem, że wszystko w końcu zostało usunięte ze śmieci po tym, jak zniknęło z zakresu?Ale chodźmy i owijamy tak jak powyżej, jeśli to uczyni analizę kodu szczęśliwym – punkouter

+1

@punkouter, problem z tym procesem myślowym polega na tym, że istnieje wiele sposobów, w jakie obiekty *** nigdy *** nie docierają do zbierania śmieci. Zarządzanie pamięcią, choć jest zautomatyzowane w .NET, nie jest bezmyślne. Rozważ klasę, która ma odniesienie do innej klasy, do której odwołuje się również obiekt, który żyje wiecznie. Wiem, że to wygląda na poważny przypadek - ale tak nie jest. *** Żaden z tych obiektów *** nie będzie śmieci, dopóki aplikacja nie zostanie zamknięta. –

+0

Ok. Więc implementacja I Disposable i wywoływanie go jest sposobem na upewnienie się, że klasa będzie zbiorem śmieci ... Być może teraz nie jest to potrzebne, ale najlepiej jest zawsze zaimplementować to i tak po prostu przyłożyć – punkouter

3

To powiadomieniem tego pola context zawiera członków jednorazowych. Oznacza to, że ci członkowie muszą mieć Dispose(), aby wywołać Garbage Collection. Dlatego chce on zaimplementować interfejs IDisposable na MemVoteManager, aby można było wywoływać Dispose() w kontekście i/lub jego elementach, które są jednorazowe.

więc zmodyfikować twój kod jako takie:

public class MemVoteManager : AbstractDataManager, IMemVoteManager, IDisposable 

a następnie wdrożyć członków interfejsu IDisposable tak:

public void Dispose() 
{ 
    // call dispose on the context and any of its members here 
} 
+0

Tak więc każda klasa w mojej klasie, która implementuje Idisposable, oznacza również, że muszę implementować iDisposable? Bez tego mogę stworzyć wyciek pamięci? Jak wspomniałem powyżej, chociaż wszystko jest zbiorem śmieci ... zarządzany kod! – punkouter

+0

@punkouter, jeśli klasa implementuje 'IDisposable', która jawnie oznacza, że ​​ma niezarządzany zasób, aby się go pozbyć. Połączenie z bazą danych na przykład *** (rzeczywiste połączenie) *** - to zasób niezarządzany. Tak więc, ponieważ masz obiekt kontekstu, który ma inne obiekty, które ostatecznie prowadzą do zasobów niezarządzanych, musisz ** upewnić się, że otrzymałeś polecenie "Dispose()". –

+0

, ale zawijanie tekstu kontekstowego za pomocą "używania" będzie takie samo jak implementowanie identyfikatora idisposable? – punkouter