Est-ce que C # a des propriétés d’extension?

Est-ce que C # a des propriétés d’extension?

Par exemple, puis-je append une propriété d’extension à DateTimeFormatInfo appelée ShortDateLongTimeFormat qui renverrait ShortDatePattern + " " + LongTimePattern ?

Non, ils n’existent pas dans C # 3.0 et ne seront pas ajoutés en 4.0. Il se trouve dans la liste des fonctionnalités souhaitées pour C #, il peut donc être ajouté à une date ultérieure.

À ce stade, les méthodes d’extension de style GetXXX sont les meilleures.

Non, ils n’existent pas.

Je sais que l’équipe C # les envisageait à un moment donné (ou du moins Eric Lippert) – avec les constructeurs et les opérateurs de vulgarisation (ceux-ci peuvent prendre un certain temps avant de se faire une idée, mais ils sont sympas…) Je n’ai vu aucune preuve qu’ils feront partie de C # 4.

EDIT: Ils ne sont pas apparus dans C # 5 et en juillet 2014, il ne semble pas non plus y avoir de C # 6.

Eric Lippert , développeur principal de l’équipe de compilation C # de Microsoft en novembre 2012, a écrit à ce sujet en octobre 2009:

  • Pourquoi pas de propriétés d’extension? – Aventures fabuleuses en codage

Pour le moment, il n’est toujours pas pris en charge par le compilateur Roslyn …

Jusqu’à présent, les propriétés d’extension n’étaient pas considérées comme suffisamment intéressantes pour être incluses dans les versions précédentes de C # standard (c.-à-d. 5 et 6).

Mais ça va …

Il y a un élément de membre d’extension dans la liste de travail C # 7 afin qu’il puisse être pris en charge dans un avenir proche. L’état actuel de la propriété d’extension peut être trouvé sur Github sous l’élément associé .

Cependant, il y a un sujet encore plus prometteur qui est le “tout étendre” en mettant l’accent sur les propriétés et les classes statiques ou même les champs.

De plus, vous pouvez utiliser une solution de contournement

Comme indiqué dans cet article , vous pouvez utiliser la fonctionnalité TypeDescriptor pour associer un atsortingbut à une instance d’object lors de l’exécution. Cependant, il n’utilise pas la syntaxe des propriétés standard.
C’est un peu différent du sucre syntaxique en ajoutant une possibilité de définir une propriété étendue comme
ssortingng Data(this MyClass instance) tant ssortingng Data(this MyClass instance) pour la méthode d’extension
ssortingng GetData(this MyClass instance) lors du stockage des données dans la classe.

J’espère que C # 7 fournira une extension complète (propriétés et champs), mais sur ce point, seul le temps nous le dira.

Et n’hésitez pas à consortingbuer car le logiciel de demain viendra de la communauté.

Mise à jour: août 2016

Comme l’équipe dotnet a publié ce qui est nouveau dans C # 7.0 et un commentaire de Mads Torgensen :

Propriétés d’extension: un stagiaire (génial!) Les a mis en œuvre au cours de l’été à titre expérimental, avec d’autres types de membres d’extension. Nous restons intéressés par cela, mais c’est un grand changement et nous devons avoir confiance que cela en vaut la peine.

Il semble que les propriétés d’extension et les autres membres soient toujours de bons candidats pour être inclus dans une future version de Roslyn, mais peut-être pas la version 7.0.

Mise à jour: mai 2017

Les membres de l’extension ont été fermés en double d’ extension tout ce qui est fermé. La discussion principale portait en fait sur l’extensibilité de type au sens large. La fonctionnalité est maintenant suivie ici en tant que proposition et a été supprimée du jalon 7.0 .

Mise à jour: août 2017 – Fonction proposée par C # 8.0

Bien que cela ne soit toujours qu’une fonctionnalité proposée , nous avons maintenant une vue plus claire de ce que serait sa syntaxe. Gardez à l’esprit que ce sera la nouvelle syntaxe pour les méthodes d’extension également:

 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 _employees = new ConditionalWeakTable(); 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; 

Semblable aux classes partielles, mais compilées en tant que classe / type distinct dans un assemblage différent. Notez que vous pourrez également append des membres et des opérateurs statiques de cette manière. Comme mentionné dans le podcast Mads Torgensen , l’extension n’aura aucun état (elle ne peut donc pas append de membres d’instance privée à la classe), ce qui signifie que vous ne pourrez pas append de données d’instance privées liées à l’instance . La raison invoquée pour cela est que cela impliquerait de gérer des dictionnaires en interne et que cela pourrait être difficile (gestion de la mémoire, etc.). Pour cela, vous pouvez toujours utiliser la technique TypeDescriptor / ConditionalWeakTable décrite précédemment et avec l’extension de propriété, la cache sous une propriété agréable.

La syntaxe est toujours sujette à changement, comme cela implique ce problème . Par exemple, les extends peuvent être remplacées par celles for lesquelles certaines personnes peuvent se sentir plus naturelles et moins liées à Java.

J’ai cessé de compter combien de fois au fil des années j’ai ouvert cette question avec l’espoir d’avoir vu cette mise en œuvre.

Enfin, nous pouvons tous nous réjouir! Microsoft va introduire ceci dans sa prochaine version C # 8.

Alors au lieu de faire ça …

 public static class IntExtensions {   public static bool Even(this int value)   {        return value % 2 == 0;   } } 

Nous pourrons enfin le faire comme ça …

 public extension IntExtension extends int { public bool Even => this % 2 == 0; } 

Source: https://blog.ndepend.com/c-8-0-features-glimpse-future/

Comme @Psyonity mentionné, vous pouvez utiliser le conditionalWeakTable pour append des propriétés aux objects existants. Combiné à ExpandoObject dynamic, vous pouvez implémenter des propriétés d’extension dynamic en quelques lignes:

 using System.Dynamic; using System.Runtime.ComstackrServices; namespace ExtensionProperties { ///  /// Dynamically associates properies to a random object instance ///  ///  /// 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"); ///  ///  /// If you get 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' you should reference Microsoft.CSharp ///  public static class ObjectExtensions { ///Stores extended data for objects private static ConditionalWeakTable extendedData = new ConditionalWeakTable(); ///  /// Gets a dynamic collection of properties associated with an object instance, /// with a lifetime scoped to the lifetime of the object ///  /// The object the properties are associated with /// A dynamic collection of properties associated with an object instance. public static dynamic DynamicProperties(this object obj) => extendedData.GetValue(obj, _ => new ExpandoObject()); } } 

Un exemple d’utilisation est dans les commentaires XML:

 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 

Parce que j’en avais récemment besoin, j’ai regardé la source de la réponse dans:

c # étendre la classe en ajoutant des propriétés

et créé une version plus dynamic:

 public static class ObjectExtenders { static readonly ConditionalWeakTable> Flags = new ConditionalWeakTable>(); public static ssortingng GetFlags(this object objectItem, ssortingng key) { return Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value; } public static void SetFlags(this object objectItem, ssortingng key, ssortingng value) { if (Flags.GetOrCreateValue(objectItem).Any(x => x.Key == key)) { Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value = value; } else { Flags.GetOrCreateValue(objectItem).Add(new ssortingngObject() { Key = key, Value = value }); } } class ssortingngObject { public ssortingng Key; public ssortingng Value; } } 

Il peut probablement être amélioré beaucoup (nommage, dynamic au lieu de chaîne), je l’utilise actuellement dans CF 3.5 avec un hackeur ConditionalWeakTable ( https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4 )