Angenommen, Sie haben eine Klasse Person:
public class Person
{
public string Name { get; set;}
public IEnumerable<Role> Roles {get; set;}
}
Ich sollte natürlich die Rollen im Konstruktor instanziieren. Jetzt habe ich es mit einer Liste wie dieser gemacht:
public Person()
{
Roles = new List<Role>();
}
Diese statische Methode habe ich jedoch im Namespace System.Linq
Entdeckt
IEnumerable<T> Enumerable.Empty<T>();
Von MSDN :
Die Methode
Empty(TResult)()
speichert eine leere Sequenz vom TypTResult
. Wenn das Objekt, das es zurückgibt, aufgelistet wird, gibt es keine Elemente zurück.In einigen Fällen ist diese Methode hilfreich, um eine leere Sequenz an eine benutzerdefinierte Methode zu übergeben, die eine
IEnumerable(T)
übernimmt. Es kann auch verwendet werden, um ein neutrales Element für Methoden wieUnion
zu generieren. Ein Beispiel für diese Verwendung von finden Sie im Abschnitt Beispiel
Also ist es besser, den Konstruktor so zu schreiben? Benutzt du es? Warum? oder wenn nicht, warum nicht?
public Person()
{
Roles = Enumerable.Empty<Role>();
}
Ich denke, die meisten Beiträge haben den Hauptpunkt verfehlt. Auch wenn Sie ein leeres Array oder eine leere Liste verwenden, handelt es sich um Objekte, die im Speicher abgelegt sind. Als Müllsammler muss er sich um sie kümmern. Wenn Sie mit Anwendungen mit hohem Durchsatz arbeiten, kann dies spürbare Auswirkungen haben.
Enumerable.Empty
erstellt kein Objekt pro Aufruf, wodurch der GC weniger belastet wird.
Befindet sich der Code an einem Ort mit geringem Durchsatz, müssen jedoch ästhetische Aspekte berücksichtigt werden.
Meiner Ansicht nach Enumerable.Empty<T>
ist besser, weil es expliziter ist: Ihr Code zeigt deutlich Ihre Absichten. Es könnte auch ein bisschen effizienter sein, aber das ist nur ein sekundärer Vorteil.
Mal sehen, wie Enumerable.Empty<T>
ist implementiert.
Es gibt EmptyEnumerable<T>.Instance
, definiert als:
internal class EmptyEnumerable<T>
{
public static readonly T[] Instance = new T[0];
}
Statische Felder für generische Typen werden pro generischem Typparameter zugewiesen. Dies bedeutet, dass die Laufzeit diese leeren Arrays nur für die vom Benutzercode benötigten Typen träge erstellen und die Instanzen so oft wie nötig wiederverwenden kann, ohne den Garbage Collector zu belasten.
Nämlich:
Debug.Assert(ReferenceEquals(Enumerable.Empty<int>(), Enumerable.Empty<int>()));
Angenommen, Sie möchten die Roles
-Eigenschaft tatsächlich auf irgendeine Weise auffüllen und kapseln sie dann ein, indem Sie den Setter privat machen und ihn in einer neuen Liste im Konstruktor initialisieren:
public class Person
{
public string Name { get; set; }
public IList<Role> Roles { get; private set; }
public Person()
{
Roles = new List<Role>();
}
}
Wenn Sie wirklich wirklich den öffentlichen Setter haben möchten, lassen Sie Roles
mit einem Wert von null
und vermeiden Sie die Objektzuordnung.
Das Problem bei Ihrem Ansatz ist, dass Sie der Sammlung keine Elemente hinzufügen können. Ich hätte eine private Struktur wie list und würde die Elemente dann als Enumerable verfügbar machen:
public class Person
{
private IList<Role> _roles;
public Person()
{
this._roles = new List<Role>();
}
public string Name { get; set; }
public void AddRole(Role role)
{
//implementation
}
public IEnumerable<Role> Roles
{
get { return this._roles.AsEnumerable(); }
}
}
Wenn Sie vorhaben, dass eine andere Klasse die Liste der Rollen erstellt (was ich nicht empfehlen würde), würde ich die Aufzählung überhaupt nicht persönlich initialisieren.
Das typische Problem beim Anzeigen der privaten Liste als IEnumerable besteht darin, dass der Client Ihrer Klasse sich durch Casting damit anlegen kann. Dieser Code würde funktionieren:
var p = new Person();
List<Role> roles = p.Roles as List<Role>;
roles.Add(Role.Admin);
Sie können dies vermeiden, indem Sie einen Iterator implementieren:
public IEnumerable<Role> Roles {
get {
foreach (var role in mRoles)
yield return role;
}
}
Das größere Problem hier wäre, Roles
als öffentliches Feld verfügbar zu machen.
folgendes sieht besser aus:
public class Person
{
public string Name { get; set; }
private List<Role> _roles = null;
public IEnumerable<Role> Roles
{
get {
if (_roles != null)
return _roles;
else
return Enumerable.Empty<Role>();
}
}
}
Und vielleicht sollten Sie es als ReadonlyCollection zurückgeben, je nachdem, wie Sie es verwenden möchten.
Und Enumerable.Empty ist hier nicht better
, nur ein bisschen effizienter, wenn Rollen normalerweise leer bleiben.