C#有扩展属性吗?
C#有扩展属性吗?
例如,我可以添加一个扩展属性DateTimeFormatInfo
称为ShortDateLongTimeFormat
将返回ShortDatePattern + " " + LongTimePattern
?
不,它们不存在于C#3.0中,不会在4.0中添加。 它在C#的function需求列表中,因此可能会在未来的date添加。
在这一点上,你可以做的最好的是GetXXX风格的扩展方法。
不,他们不存在。
我知道C#团队正在考虑他们(或者至less是Eric Lippert) – 还有扩展的构造器和操作员(这些可能需要一段时间才能让你头脑清醒,但是很酷……)但是,没有看到任何证据表明他们将成为C#4的一部分。
编辑:他们没有出现在C#5中,截至2014年7月,它看起来不会在C#6中。
微软C#编译团队的首席开发人员Eric Lippert在2012年11月的一篇博文中对2009年10月的博客进行了评论:
- 为什么没有扩展属性? – 编码中的神话般的冒险
目前它还不支持Roslyn编译器开箱即用…
到目前为止,扩展属性并没有被认为足以包含在以前版本的C#标准(即5和6)中。
但它会…
C#7工作列表中有一个扩展成员项目,因此在不久的将来可能会得到支持。 扩展属性的当前状态可以在Github的相关项目下find。
然而,还有一个更有希望的话题就是“扩展一切” ,尤其是属性和静态类甚至是领域。
此外,您可以使用一种解决方法
如本文所述 ,您可以使用TypeDescriptor
function在运行时将属性附加到对象实例。 但是,它不使用标准属性的语法。
这与语法糖有点不同,增加了定义一个扩展属性的可能性
string Data(this MyClass instance)
作为扩展方法的别名
string GetData(this MyClass instance)
因为它将数据存储到类中。
我希望C#7将提供一个全function的扩展(属性和字段),但是在这一点上,只有时间才能说明问题。
随着明天的软件会来自社区,随时做出贡献。
更新:2016年8月
正如dotnet小组在C#7.0中发表的新内容以及Mads Torgensen的评论:
扩展属性:我们有一个(辉煌!)实习生,在暑假期间作为一个实验与其他types的扩展成员一起实施它们。 我们仍然对此感兴趣,但这是一个巨大的变化,我们需要确信这是值得的。
看来,扩展属性和其他成员,仍然是很好的候选人将包括在未来的版本的Roslyn,但也许不是7.0的。
更新:2017年5月
扩展成员已被closures,作为扩展所有closures的问题的副本。 主要的讨论实际上是广义上的types可扩展性。 此function现在作为提案进行跟踪,并已从7.0里程碑中删除。
正如@Psyonity所提到的,你可以使用conditionalWeakTable来为现有对象添加属性。 结合dynamicExpandoObject,您可以在几行中实现dynamic扩展属性:
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()); } }
用法示例在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
因为我最近需要这个,所以我查看了答案的来源:
c#通过添加属性来扩展类
并创build了一个更加dynamic的版本:
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; } }
它可能可以改善很多(命名,dynamic而不是string),我目前在CF 3.5中使用这个与一个hacky ConditionalWeakTable( https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4 )