Verfügt C# über Erweiterungseigenschaften?
Kann ich zum Beispiel eine Erweiterungseigenschaft hinzufügen zu DateTimeFormatInfo
genannt. ShortDateLongTimeFormat
was Folgendes ergeben würde ShortDatePattern + " " + LongTimePattern
?
Verfügt C# über Erweiterungseigenschaften?
Kann ich zum Beispiel eine Erweiterungseigenschaft hinzufügen zu DateTimeFormatInfo
genannt. ShortDateLongTimeFormat
was Folgendes ergeben würde ShortDatePattern + " " + LongTimePattern
?
Bis jetzt wurden die Erweiterungseigenschaften nicht als wertvoll genug angesehen, um in die früheren Versionen des C#-Standards aufgenommen zu werden. C# 7 y C# 8.0 haben diesen Vorschlag als Champion gesehen, aber er wurde noch nicht veröffentlicht, vor allem, weil sie es von Anfang an richtig machen wollen, auch wenn es bereits eine Umsetzung gibt.
Es gibt eine Erweiterungsmitglieder Element im C# 7 Arbeitsliste so dass sie möglicherweise in naher Zukunft unterstützt wird. Der aktuelle Status der Erweiterungseigenschaft ist zu finden unter Github unter dem entsprechenden Punkt .
Es gibt jedoch ein noch vielversprechenderes Thema, nämlich die "alles erweitern" mit dem Schwerpunkt auf besonderen Eigenschaften und statischen Klassen oder sogar Feldern.
Wie in dieser Artikel können Sie die TypeDescriptor
die Möglichkeit, ein Attribut zur Laufzeit an eine Objektinstanz anzuhängen. Dabei wird jedoch nicht die Syntax der Standardeigenschaften verwendet.
Es ist ein wenig anders als nur syntaktischer Zucker, der die Möglichkeit bietet, eine erweiterte Eigenschaft zu definieren wie
string Data(this MyClass instance)
als Alias für die Erweiterungsmethode
string GetData(this MyClass instance)
da sie Daten in der Klasse speichert.
Ich hoffe, dass C#7 eine voll ausgestattete Erweiterung alles (Eigenschaften und Felder), aber in diesem Punkt, nur die Zeit wird zeigen.
Und tragen Sie gerne dazu bei, denn die Software von morgen wird von der Gemeinschaft kommen.
Aktualisierung: August 2016
Wie das dotnet-Team veröffentlichte Was ist neu in C# 7.0 und aus einem Kommentar von Mads Torgensen :
Erweiterungseigenschaften: Wir hatten einen (brillanten!) Praktikanten, der sie Sommer als Experiment implementiert, zusammen mit anderen Arten von Erweiterungs Mitglieder. Wir sind weiterhin daran interessiert, aber es ist eine große Veränderung und wir müssen sicher sein, dass es sich lohnt.
Es scheint, dass Erweiterungseigenschaften und andere Mitglieder immer noch gute Kandidaten sind, um in eine zukünftige Version von Roslyn aufgenommen zu werden, aber vielleicht nicht in die Version 7.0.
Aktualisierung: Mai 2017
Die Erweiterungsmitglieder wurde geschlossen als Duplikat von Erweiterung alles Problem die ebenfalls geschlossen ist. Die Hauptdiskussion drehte sich um die Erweiterbarkeit von Typen im weiteren Sinne. Die Funktion wird nun verfolgt hier als Vorschlag und wurde entfernt aus 7,0 Meilenstein .
Update: August, 2017 - C# 8.0 vorgeschlagene Funktion
Es ist zwar immer noch nur ein vorgeschlagen haben wir nun eine klarere Vorstellung davon, wie die Syntax aussehen könnte. Beachten Sie, dass dies auch die neue Syntax für Erweiterungsmethoden sein wird:
public interface IEmployee
{
public decimal Salary { get; set; }
}
public class Employee
{
public decimal Salary { get; set; }
}
public extension MyPersonExtension extends Person : IEmployee
{
private static readonly ConditionalWeakTable<Person, Employee> _employees =
new ConditionalWeakTable<Person, Employee>();
public decimal Salary
{
get
{
// `this` is the instance of Person
return _employees.GetOrCreate(this).Salary;
}
set
{
Employee employee = null;
if (!_employees.TryGetValue(this, out employee)
{
employee = _employees.GetOrCreate(this);
}
employee.Salary = value;
}
}
}
IEmployee person = new Person();
var salary = person.Salary;
Ähnlich wie partielle Klassen, aber als separate Klasse/Typ in einer anderen Assembly kompiliert. Beachten Sie, dass Sie auf diese Weise auch statische Mitglieder und Operatoren hinzufügen können. Wie bereits in Mads Torgensen-Podcast , die Erweiterung hat keinen Status (sie kann also keine privaten Instanzmitglieder zur Klasse hinzufügen), was bedeutet, dass Sie keine privaten Instanzdaten hinzufügen können, die mit der Instanz verknüpft sind . Der Grund dafür ist, dass es bedeuten würde, intern Wörterbücher zu verwalten, und das könnte schwierig sein (Speicherverwaltung usw.). Hierfür können Sie immer noch die TypeDescriptor
/ ConditionalWeakTable
Technik, die zuvor beschrieben wurde, und mit der Eigenschaftserweiterung, versteckt es unter einer schönen Eigenschaft.
Die Syntax kann sich noch ändern, was bedeutet, dass diese Ausgabe . Zum Beispiel, extends
könnte ersetzt werden durch for
was manche als natürlicher und weniger javabezogen empfinden mögen.
Update Dezember 2018 - Rollen, Erweiterungen und statische Schnittstellenmitglieder
Erweiterung alles hat es nicht in C# 8.0 geschafft, weil einige der Nachteile, die am Ende dieses GitHub-Ticket . Es wurde also untersucht, wie das Design verbessert werden kann. Hier Mads Torgensen erklärt, was sind Rollen und Erweiterungen und wie sie sich unterscheiden:
Rollen ermöglichen die Implementierung von Schnittstellen für bestimmte Werte eines bestimmten Typs. Erweiterungen ermöglichen die Implementierung von Schnittstellen für alle Werte eines gegebenen Typs innerhalb einer bestimmten Coderegion implementiert werden.
Es kann an einer Aufteilung des vorherigen Vorschlags in zwei Anwendungsfälle gesehen werden. Die neue Syntax für die Erweiterung würde so aussehen:
public extension ULongEnumerable of ulong
{
public IEnumerator<byte> GetEnumerator()
{
for (int i = sizeof(ulong); i > 0; i--)
{
yield return unchecked((byte)(this >> (i-1)*8));
}
}
}
dann könnten Sie dies tun:
foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
WriteLine($"{e.Current:X}");
}
Und für eine statische Schnittstelle :
public interface IMonoid<T> where T : IMonoid<T>
{
static T operator +(T t1, T t2);
static T Zero { get; }
}
Hinzufügen einer Erweiterungseigenschaft en int
und behandeln die int
como IMonoid<int>
:
public extension IntMonoid of int : IMonoid<int>
{
public static int Zero => 0;
}
Nein, die gibt es nicht.
Ich weiß, dass das C#-Team sie zu einem bestimmten Zeitpunkt in Erwägung gezogen hat (oder zumindest Eric Lippert) - zusammen mit Erweiterungskonstruktoren und -operatoren (es kann eine Weile dauern, bis man sie verstanden hat, aber sie sind cool...) Ich habe jedoch keine Hinweise darauf gesehen, dass sie Teil von C# 4 sein werden.
EDIT: Sie erschienen nicht in C# 5, und seit Juli 2014 sieht es auch nicht so aus, als ob sie in C# 6 erscheinen würden.
Eric Lippert der Hauptentwickler des C#-Compiler-Teams bei Microsoft (bis November 2012), bloggte darüber im Oktober 2009:
Update (Dank an @chaost für den Hinweis auf diese Aktualisierung):
Mads Torgersen: "Extension everything" hat es nicht in C# 8.0 geschafft. Es hat sich, wenn man so will, in einer sehr spannenden Debatte über die weitere Zukunft der Sprache "verfangen", und jetzt wollen wir sicherstellen, dass wir es nicht auf eine Weise hinzufügen, die diese zukünftigen Möglichkeiten behindert. Manchmal ist Sprachdesign ein sehr langes Spiel!"
出典 Kommentarbereich in https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/
Ich habe aufgehört zu zählen, wie oft ich im Laufe der Jahre diese Frage mit der Hoffnung eröffnet habe, sie umgesetzt zu sehen.
Nun, endlich können wir uns alle freuen! Microsoft wird dies in seiner kommenden C# 8 Version einführen.
Anstatt dies zu tun...
public static class IntExtensions
{
public static bool Even(this int value)
{
return value % 2 == 0;
}
}
Wir werden es endlich so machen können...
public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
Wie @Psyonity bereits erwähnt hat, können Sie die conditionalWeakTable verwenden, um Eigenschaften zu bestehenden Objekten hinzuzufügen. In Kombination mit dem dynamischen ExpandoObject könnten Sie dynamische Erweiterungseigenschaften in wenigen Zeilen implementieren:
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace ExtensionProperties
{
/// <summary>
/// Dynamically associates properies to a random object instance
/// </summary>
/// <example>
/// var jan = new Person("Jan");
///
/// jan.Age = 24; // regular property of the person object;
/// jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
///
/// if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
/// Console.WriteLine("Jan drinks too much");
/// </example>
/// <remarks>
/// If you get 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' you should reference Microsoft.CSharp
/// </remarks>
public static class ObjectExtensions
{
///<summary>Stores extended data for objects</summary>
private static ConditionalWeakTable<object, object> extendedData = new ConditionalWeakTable<object, object>();
/// <summary>
/// Gets a dynamic collection of properties associated with an object instance,
/// with a lifetime scoped to the lifetime of the object
/// </summary>
/// <param name="obj">The object the properties are associated with</param>
/// <returns>A dynamic collection of properties associated with an object instance.</returns>
public static dynamic DynamicProperties(this object obj) => extendedData.GetValue(obj, _ => new ExpandoObject());
}
}
Ein Anwendungsbeispiel finden Sie in den XML-Kommentaren:
var jan = new Person("Jan");
jan.Age = 24; // regular property of the person object;
jan.DynamicProperties().NumberOfDrinkingBuddies = 27; // not originally scoped to the person object;
if (jan.Age < jan.DynamicProperties().NumberOfDrinkingBuddies)
{
Console.WriteLine("Jan drinks too much");
}
jan = null; // NumberOfDrinkingBuddies will also be erased during garbage collection
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
21 Stimmen
Ich wollte eine Erweiterungsmethode namens IsNull für Nullable<T> hinzufügen, die einfach ! HasValue zurückgibt. .IsNull() ist auf jeden Fall weniger hübsch als .IsNull
1 Stimmen
Ich finde dies nützlich für trinäre Operatoren
?
2 Stimmen
Ich wollte, dass dies die Java's
enum
s, die Eigenschaften und Methoden haben können. C#senum
s können keine Eigenschaften oder Methoden haben, aber Sie puede Erweiterungsmethoden für sie erstellen. Diese Frage war nützlich für mich, und sollte nicht geschlossen werden.0 Stimmen
Obwohl es, wie viele gesagt haben, derzeit keine Pläne gibt, dies in die Sprache aufzunehmen, gibt es keinen Grund, warum dies nicht möglich sein sollte. Die Tatsache, dass F# nicht nur Erweiterungseigenschaften, sondern auch statische Erweiterungen hat, beweist für mich, dass es zumindest eine gute Idee ist.
2 Stimmen
Es sollte eine gemacht werden