method - ¿C#tiene propiedades de extensión?
extended methods c# (6)
Por el momento, el compilador de Roslyn aún no lo admite de forma inmediata.
Hasta ahora, las propiedades de la extensión no se consideraban lo suficientemente valiosas como para incluirlas en las versiones anteriores del estándar C # (es decir, 5 y 6).
Pero será ...
Hay un elemento de miembros de la extensión en la lista de trabajo de C # 7, por lo que puede ser compatible en un futuro próximo. El estado actual de la propiedad de extensión se puede encontrar en Github bajo el elemento relacionado .
Sin embargo, hay un tema aún más prometedor que es "extender todo" con un enfoque especial en propiedades y clases estáticas o incluso campos.
Además puedes utilizar una solución alternativa.
Como se especifica en este article , puede usar la capacidad TypeDescriptor
para adjuntar un atributo a una instancia de objeto en tiempo de ejecución. Sin embargo, no está utilizando la sintaxis de las propiedades estándar.
Es un poco diferente de solo azúcar sintáctica, lo que agrega la posibilidad de definir una propiedad extendida como
string Data(this MyClass instance)
como un alias para el método de extensión
string GetData(this MyClass instance)
ya que almacena datos en la clase.
Espero que C # 7 proporcione una extensión con todas las funciones (propiedades y campos), sin embargo, en ese punto, solo el tiempo lo dirá.
Y siéntase libre de contribuir ya que el software del mañana vendrá de la comunidad.
Actualización: agosto 2016
Como el equipo de dotnet publicó lo nuevo en C # 7.0 y de un comentario de Mads Torgensen :
Propiedades de extensión: tuvimos un (¡brillante!) Pasante implementado durante el verano como un experimento, junto con otros tipos de miembros de extensión. Seguimos interesados en esto, pero es un gran cambio y debemos sentirnos seguros de que vale la pena.
Parece que las propiedades de extensión y otros miembros, todavía son buenos candidatos para ser incluidos en una futura versión de Roslyn, pero tal vez no sea la versión 7.0.
Actualización: mayo 2017
Los miembros de la extensión se han cerrado como un duplicado de la extensión, todo está cerrado también. La discusión principal fue, de hecho, sobre la extensibilidad del tipo en un sentido amplio. Ahora se hace un seguimiento de la función github.com/dotnet/csharplang/issues/192 y se ha eliminado del hito 7.0 .
Actualización: agosto de 2017 - C # 8.0 característica propuesta
Si bien sigue siendo solo una característica propuesta , ahora tenemos una visión más clara de cuál sería su sintaxis. Tenga en cuenta que esta también será la nueva sintaxis de los métodos de extensión:
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;
Similar a las clases parciales, pero compilado como una clase / tipo separado en un ensamblaje diferente. Tenga en cuenta que también podrá agregar miembros y operadores estáticos de esta manera. Como se mencionó en el podcast de Mads Torgensen , la extensión no tendrá ningún estado (por lo que no puede agregar miembros de instancia privados a la clase), lo que significa que no podrá agregar datos de instancia privada vinculados a la instancia . La razón invocada para ello es que implicaría administrar diccionarios internos y podría ser difícil (administración de memoria, etc.). Para esto, todavía puede usar la técnica TypeDescriptor
/ ConditionalWeakTable
descrita anteriormente y con la extensión de la propiedad, la oculta bajo una propiedad agradable.
La sintaxis aún está sujeta a cambios, ya que implica este issue . Por ejemplo, las extends
podrían reemplazarse por las cuales algunos pueden sentirse más naturales y menos relacionados con Java.
¿C # tiene propiedades de extensión?
Por ejemplo, ¿puedo agregar una propiedad de extensión a DateTimeFormatInfo
llamada ShortDateLongTimeFormat
que devolvería ShortDatePattern + " " + LongTimePattern
?
Como recientemente lo necesitaba, miré la fuente de la respuesta en:
c # extender la clase agregando propiedades
y creó una versión más dinámica:
public static class ObjectExtenders
{
static readonly ConditionalWeakTable<object, List<stringObject>> Flags = new ConditionalWeakTable<object, List<stringObject>>();
public static string GetFlags(this object objectItem, string key)
{
return Flags.GetOrCreateValue(objectItem).Single(x => x.Key == key).Value;
}
public static void SetFlags(this object objectItem, string key, string 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 stringObject()
{
Key = key,
Value = value
});
}
}
class stringObject
{
public string Key;
public string Value;
}
}
Probablemente se puede mejorar mucho (nomenclatura, dinámica en lugar de cadena), actualmente uso esto en CF 3.5 junto con una ConditionalWeakTable ( https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4 )
Como se mencionó @Psyonity, puede usar la condicional TablaDebil para agregar propiedades a los objetos existentes. Combinado con el ExpandoObject dinámico, podría implementar propiedades de extensión dinámicas en unas pocas líneas:
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());
}
}
Un ejemplo de uso está en los comentarios 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
Dejé de contar cuántas veces a lo largo de los años abrí esta pregunta con la esperanza de haberla implementado.
Bueno, finalmente todos podemos regocijarnos! Microsoft va a presentar esto en su próximo lanzamiento de C # 8.
Así que en lugar de hacer esto ...
public static class IntExtensions
{
public static bool Even(this int value)
{
return value % 2 == 0;
}
}
Por fin podremos hacerlo así ...
public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
Fuente: https://blog.ndepend.com/c-8-0-features-glimpse-future/
No, no existen en C # 3.0 y no se agregarán en 4.0. Está en la lista de funciones que desea para C #, por lo que se puede agregar en una fecha futura.
En este punto, lo mejor que puede hacer es obtener métodos de extensión de estilo GetXXX.
No, no existen.
Sé que el equipo de C # los estaba considerando en un momento dado (o al menos Eric Lippert lo estaba), junto con los constructores y operadores de extensiones (es posible que se demoren un poco en eso, pero son geniales ...) Sin embargo, no tengo No he visto ninguna evidencia de que formarán parte de C # 4.
EDIT: No aparecieron en C # 5, y a partir de julio de 2014 tampoco parece que vaya a estar en C # 6.
Eric Lippert , el desarrollador principal del equipo de compilación de C # en Microsoft hasta noviembre de 2012, publicó un blog sobre esto en octubre de 2009: