Laden...

Statische Codeanalyse mahnt CA1001 nicht an[=> korrekt]

Erstellt von Paschulke vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.091 Views
P
Paschulke Themenstarter:in
69 Beiträge seit 2011
vor 7 Jahren
Statische Codeanalyse mahnt CA1001 nicht an[=> korrekt]

Hallo!

Ich bin irritiert über die statische Codanalyse:
Ich habe eine Klasse, die ein privates Feld besitzt, das IDisposable implementiert. Die Klasse selber besitzt zurzeit keine Dispose-Methode. Wenn ich CA1001 Types that own disposable fields should be disposable richtig verstehe, sollte die statische Codeanalyse nun diese Warnung bringen, wenn ich sie laufen lasse. Tut sie aber nicht. Lt. Codeanalyse ist mein Code in Ordnung.

Verstehe ich die Regel falsch? Oder gibt es Konstellationen in denen die statische Codeanalyse den Fehler nicht erkennt?

16.806 Beiträge seit 2008
vor 7 Jahren

Eine Klasse, die Methoden (hier Dispose) eines Interfaces (hier IDisposable) nicht implementieren, sind nicht kompilierbar.
Ich bezweifle also, dass der Code in Ordnung ist. 🤔 Oder hat Deine Klasse nicht mal IDisposable? Ohne Code muss man immer raten...

Und was für ein Analysetool verwendest Du denn?
Der Code aus der MSDN funktioniert mit VS 2015 Code Analyse einwandfrei. Haste das denn selbst mal als Kontrolle ausgeführt??

P
Paschulke Themenstarter:in
69 Beiträge seit 2011
vor 7 Jahren

Grundsätzlich sieht mein Code schon so aus, wie Deiner. Ich habe mich etwas missverständlich ausgedrückt. Natürlich hat die Klasse, die IDisposable implementiert eine Dispose Methode. Ich meinte die Klasse, die ein Feld vom Typ des IDisposables besitzt, hat keine Dispose Methode...

Warnt die Codeanalyse nur, wenn das Feld innerhalb der Klasse erstellt wurde?
Ich fürchte das Problem liegt darin, dass ich einen IoC Container (Castle Windsor) verwende, der mir das zu disposende Objekt über Constructor Injection in meine Klasse hinein reicht. Der IoC Container erstellt dabei das Objekt. Ist er evtl. so schlau das Objekt bei Zeiten auch zu disposen, sodass ich mich gar nicht darum zu kümmern brauche? Dann wäre ja tatsächlich alles in Ordnung.

16.806 Beiträge seit 2008
vor 7 Jahren

Es warnt nur, wenn das Feld private ist.
Und Felder sollten immer private sein.

Wenn es also nicht innerhalb der Klasse erstellt wird, dann hast Du (offensichtlich?) kein privates Feld.

P
Paschulke Themenstarter:in
69 Beiträge seit 2011
vor 7 Jahren

Das Feld ist private - sogar private readonly. Aber es wird aber außerhalb (vom IoC Container) erzeugt und über den Konstrukor in meine Klasse hineingereicht.

Ich hatte CA1001 so verstanden, dass die Codeanalyse (VS) immer warnt, wenn ein Feld disposable ist - unabhängig davon wer das Feld erstellt. Offensichtlich ist das nicht so. Das new ist entscheidend.

Dann muss ich mal in der Doku von Castle nachlesen, ob ich mich um das Dispose kümmern muss.

Vielen Dank, Abt für Deine Hilfe!

W
955 Beiträge seit 2010
vor 7 Jahren

Dann muss ich mal in der Doku von Castle nachlesen, ob ich mich um das Dispose kümmern muss. Welchen Lifestyle hat das Objekt?

1.040 Beiträge seit 2007
vor 7 Jahren

Wenn du das Objekt - auf welchem Wege auch immer - von außen mit in die Klasse reichst, dann muss sich in meiner Welt die äußere Klasse um das Dispose kümmern, da nur sie weiß, wann das Objekt nicht mehr benötigt wird.

Beispiel:

public class MeineTolleSuperKlasse
{
	public MeineTolleSuperKlasse()
	{
		using (var stream = new FileStream(@"C:\test.txt", FileMode.Open))
		{
			stream.ReadByte();
			//Mache irgendwas

			var streamHelper = new StreamHelper(stream);
			streamHelper.Reset();

			stream.ReadByte();
			//Mache irgendwas
		}
	}
}

public class StreamHelper
{
	private readonly FileStream _stream;

	public StreamHelper(FileStream stream)
	{
		_stream = stream;
	}

	public void Reset()
	{
		_stream.Position = 0;
	}
}

Würde man jetzt hier erwarten, dass sich der StreamHelper um das Dispose kümmern soll?
MeineTolleSuperKlasse ist in deinem Fall der IoC-Container/Castle. =)

EDIT sagt noch, dass es auch Fälle gibt, in denen Objekte in IoC-Containern als SingleInstance erzeugt werden, er wäre katastrophal, wenn die zwischendurch einer abräumt (falls jemand nachfragt: mir ist aktuell kein praktischer Fall bekannt 😉).

16.806 Beiträge seit 2008
vor 7 Jahren

Sobald etwas von Außen rein kommt, ist auch die Aussenstelle für das Disposen verantwortlich.
Die statische Codeanalyse ist in diesem Fall korrekt.

D
985 Beiträge seit 2014
vor 7 Jahren

Ausnahmen von dieser Regel werden dann bei der Übergabe entsprechend vermerkt, so wie das z.B. bei StreamWriter mit dem übergebenen Stream erfolgt.

P
Paschulke Themenstarter:in
69 Beiträge seit 2011
vor 7 Jahren

Welchen Lifestyle hat das Objekt?

Transient

W
955 Beiträge seit 2010
vor 7 Jahren

Bei transienten Objekten kann der Container nicht wissen wie lange du ihn brauchst. Schließlich könntest du auch mehrere Exemplare des Objektes anfordern wollen (z.B. immer wenn der Benutzer Speichern klickt willst du über das Uow Speichern, dieses verwerfen und ein neues anfordern).
Wenn die Klasse die das Objekt injiziert bekommt den Lifestyle Singleton hat wird das transiente Objekt die gesamte Zeit an diesem Singleton kleben bleiben, wird dann der Conatainer verworfen wird die Dispose-Methode aller Disposables des Containers aufgerufen. Man sollte sich überlegen ob es OK ist an ein Singleton ein Transientes Objekt zu binden.
Ansonsten ist es üblich transiente Objekte über eine Facility reinzugeben. Die hat dann eine Methode Destroy über die man das nicht mehr benötigte Objekt zurückgeben kann.