Frage

Der Code sieht wie folgt:

namespace Test
{
    public interface IMyClass
    {
        List<IMyClass> GetList();
    }

    public class MyClass : IMyClass
    {
        public List<IMyClass> GetList()
        {
            return new List<IMyClass>();
        }
    }
}

Wenn ich Code-Analyse starten erhalte ich die folgende Empfehlung.

  

Warnung 3 CA1002: Microsoft.Design: Change 'Liste' in 'IMyClass.GetList ()' zu verwenden, Sammlung, oder Readonlycollection KeyedCollection

Wie soll ich dieses Problem beheben und was ist eine gute Praxis hier?

War es hilfreich?

Lösung

Zur Beantwortung des „Warum“ Teil der Frage, warum nicht List<T>, Die Gründe dafür sind Zukunftssicherheit und API Einfachheit.

Zukunftssicherheit

List<T> nicht durch Subklassen es zu sein, leicht erweiterbar ausgelegt; es ist für die interne Implementierungen schnell zu sein. Sie werden bemerken, die Methoden auf nicht virtuell sind und kann so nicht außer Kraft gesetzt werden, und es gibt keine Haken in seine Add / Insert / Remove Operationen.

Das bedeutet, dass, wenn Sie das Verhalten der Sammlung in der Zukunft ändern müssen (zB null Objekte abzulehnen, die Menschen versuchen, hinzuzufügen oder zusätzliche Arbeit zu verrichten, wenn dies geschieht, wie Ihre Klasse Zustand zu aktualisieren), dann müssen Sie ändern Sie die Art der Sammlung Sie eine Rückkehr zu Ihnen Unterklasse kann, die eine Bruch Schnittstelle ändern wird (natürlich die Semantik der Dinge zu ändern, wie nicht null erlauben kann auch eine Schnittstelle ändern, aber Dinge wie Ihre interne Klasse Zustand zu aktualisieren wäre nicht ).

So entweder durch eine Klasse zurückkehrt, die leicht wie Collection<T> subclassed werden kann, oder eine Schnittstelle wie IList<T>, ICollection<T> oder IEnumerable<T> können Sie Ihre interne Implementierung ändern, um eine andere Sammlung Art, um Ihre Bedürfnisse zu erfüllen, ohne den Code der Verbraucher zu brechen weil es noch zurückgegeben werden können sie erwarten als Typ sind.

API Einfachheit

List<T> enthält viele nützliche Funktionen wie BinarySearch, Sort und so weiter. Allerdings, wenn es sich um eine Sammlung Sie Belichtung werden dann ist es wahrscheinlich, dass Sie die Semantik der Liste steuern, und nicht die Verbraucher. So, während die Klasse intern benötigen diese Operationen ist es sehr unwahrscheinlich ist, dass die Verbraucher der Klasse wollen würde (oder sogar sollte) sie nennen.

Als solche durch eine einfachere Sammlung Klasse oder Schnittstelle bietet, die Anzahl der Mitglieder reduzieren, die die Benutzer des API sehen, und machen es einfacher für sie zu verwenden.

Andere Tipps

Ich würde es persönlich erklären eine Schnittstelle statt einer konkreten Sammlung zurückzukehren. Wenn Sie wirklich Zugang auflisten möchten, verwenden Sie IList<T> . Ansonsten betrachten ICollection<T> und IEnumerable<T> .

Es ist vor allem über eigene Implementierungen weg anstelle des Aussetzens des List-Objekt abstrahiert direkt manipuliert werden.

Es ist keine gute Praxis andere Objekte (oder Personen) zu lassen, um den Zustand Ihrer Objekte direkt ändern. Denken Sie Eigenschaft Getter / Setter.

Sammlung -> Für normale Sammlung
Readonlycollection -> Für Sammlungen, die nicht
geändert werden sollen, KeyedCollection. -> Wenn Sie Wörterbücher wollen stattdessen

Wie es zu beheben, hängt von was Sie Ihre Klasse wollen, und der Zweck des GetList () -Methode zu tun. Können Sie das näher erläutern?

In dieser Art von Fall, dass ich versuchen, in der Regel die geringste Menge an implemententation zu belichten, die benötigt wird. Wenn die Verbraucher müssen nicht wissen, dass Sie tatsächlich mit einer Liste werden dann brauchen Sie nicht eine Liste zurückzukehren. Durch die Rückgabe als Microsoft schlägt vor, eine Sammlung Sie darüber hinwegtäuschen, dass Sie eine Liste von den Verbrauchern Ihrer Klasse und zu isolieren, um sie gegen eine interne Änderung verwenden.

Ich glaube nicht, dass jemand den „Warum“ Teil noch ... so geht hier beantwortet hat. Der Grund, „warum“ Sie „sollte“ verwendet ein Collection<T> anstelle einem List<T> da ist, wenn Sie ein List<T> aussetzen, dann jeder, den Zugang zu Ihrem Objekt bekommt kann die Elemente in der Liste ändern. Während Collection<T> soll, um anzuzeigen, dass Sie Ihre eigenen „Hinzufügen“ machen, „Entfernen“, etc Methoden.

Sie wahrscheinlich nicht brauchen, sich darum zu kümmern, weil Sie wahrscheinlich die Schnittstelle für sich selbst sind Codierung nur (oder vielleicht ein paar Kollegen). Hier ist ein weiteres Beispiel, das Sinn machen könnte.

Wenn Sie eine öffentliche Array, zB:

public int[] MyIntegers { get; }

Sie würden denken, dass, weil es nur ein „get“ Accessor, dass niemand kann Schlamassel mit den Werten, aber das ist nicht wahr. Jeder kann die Werte innerhalb dort ändern, nur wie folgt aus:

someObject.MyIngegers[3] = 12345;

Persönlich würde ich nur List<T> in den meisten Fällen. Aber wenn Sie eine Klassenbibliothek entwerfen, dass Sie gehen, um zufällige Entwickler zu geben, und Sie müssen über den Zustand der Objekte verlassen ... dann wollen Sie Ihre eigene Sammlung machen und sie verriegeln von dort nach unten: )

etwas hinzufügen, obwohl es eine lange Zeit gewesen ist, da dies gefragt wurde.

Wenn Sie Ihre Liste Typ aus List<T> statt Collection<T> leitet, können Sie nicht auf die geschützten virtuellen Methoden implementieren, die Geräte Collection<T>. Was dies bedeutet, ist, dass Sie abgeleiteten Typ nicht in Fall reagieren können Änderungen an der Liste vorgenommen werden. Dies liegt daran, List<T> vorausgesetzt, dass Sie sich bewusst sind, wenn Sie Elemente hinzufügen oder entfernen. In der Lage zu Reaktion auf Meldungen ist ein Overhead und damit nicht List<T> nicht bieten.

In den Fällen, wenn externer Code Zugriff auf Ihre Sammlung hat, können Sie nicht von Kontrolle, wenn ein Element hinzugefügt oder entfernt wird. Daher Collection<T> bietet eine Möglichkeit, zu wissen, wann die Liste geändert wurde.

Ich sehe kein Problem nicht so etwas wie

mit der Rückkehr
this.InternalData.Filter(crteria).ToList();

Wenn ich wieder eine getrennte Kopie von internen Daten oder frei stehendes Ergebnis einer Datenabfrage - ich kann sicher List<TItem> zurückzukehren, ohne von Implementierungsdetails aussetzt, und lassen Sie die zurückgegebenen Daten in der bequem bedienen Art und Weise.

Aber das hängt davon ab, welche Art von Verbrauchern Ich erwarte, dass - wenn dies eine etwas wie Datenraster ist ich zurückkehren bevorzugen IEnumerable<TItem> , die die kopierte Liste der Elemente werden sowieso in den meisten Fällen:)

Nun, die Collection-Klasse ist wirklich nur eine Wrapper-Klasse um andere Sammlungen ihre Implementierungsdetails und andere Funktionen zu verbergen. Ich rechne damit, das hat etwas mit der Eigenschaft versteckt Codierungsmuster in objektorientierten Sprachen zu tun.

Ich glaube, Sie sollten sich keine Sorgen darüber, aber wenn Sie wirklich den Code-Analyse-Tool wollen bitte, tun Sie einfach die folgenden Schritte aus:

//using System.Collections.ObjectModel;

Collection<MyClass> myCollection = new Collection<MyClass>(myList);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top