题
C# 有扩展属性吗?
例如,我可以添加一个扩展属性吗 DateTimeFormatInfo
被称为 ShortDateLongTimeFormat
这会返回 ShortDatePattern + " " + LongTimePattern
?
解决方案
它们在C#3.0中不存在,不会在4.0中添加。它位于C#的功能需求列表中,因此可能会在将来添加。
此时,您可以做的最好的是GetXXX样式扩展方法。
其他提示
不,它们不存在。
我知道 C# 团队曾一度考虑过它们(或者至少 Eric Lippert 曾经考虑过)——以及扩展构造函数和运算符(这些可能需要一段时间才能让您头脑清醒,但很酷...)但是,我还没有没有看到任何证据表明它们将成为 C# 4 的一部分。
编辑:它们没有出现在 C# 5 中,并且截至 2014 年 7 月,它看起来也不会出现在 C# 6 中。
埃里克·利珀特, 2012 年 11 月之前,微软 C# 编译器团队的首席开发人员在 2009 年 10 月的博客中谈到了这一点:
目前,Roslyn编译器仍然不支持开箱即用......
到目前为止,扩展属性的价值还不足以包含在以前版本的C#标准中。 C#7 和 C#8.0 已将此视为提案冠军,但尚未发布,最重要的是因为即使已经有实施,他们也想要实现从一开始就是。
但它会......
分机会员 项目< strong> C#7工作清单 因此可能会在不久的将来得到支持。扩展属性的当前状态可以在 Github相关项目下找到。
然而,有一个更有希望的主题是“扩展一切”重点关注特别属性和静态类甚至字段。
此外,您可以使用解决方法
如文章中所述,您可以使用 TypeDescriptor
在运行时将属性附加到对象实例的功能。但是,它没有使用标准属性的语法。
它与语法糖略有不同,增加了定义扩展属性的可能性,例如
string Data(此MyClass实例)
作为扩展方法的别名
string GetData(这个MyClass实例)
,因为它将数据存储到类中。
我希望C#7能提供全功能的扩展(属性和字段),但是在这一点上,只有时间会证明。
随着明天的软件来自社区,随时可以做出贡献。
更新:2016年8月
随着dotnet团队发布 C#7.0中的新功能和 Mads Torgensen <的评论/一个>:
扩展属性:我们有一个(辉煌!)实习生实施它们 夏天作为实验,以及其他类型的延伸 成员。我们仍然对此感兴趣,但这是一个很大的变化,我们 需要确信它值得。
似乎扩展属性和其他成员仍然是未来发布的Roslyn中的优秀候选者,但可能不是7.0版本。
更新:2017年5月
扩展会员 已被关闭 扩展所有问题 也已关闭。 主要的讨论实际上是广义上的类型可扩展性。 现在, 此处作为提案 跟踪该功能,从 7.0里程碑 。
更新:2017年8月 - C#8.0建议功能
虽然它仍然只是提议的功能,但我们现在可以更清楚地了解它的语法。请记住,这将是ne
更新(感谢 @chaost 指出此更新):
Mads Torgersen:“扩展所有内容并没有进入C#8.0。如果你愿意的话,它会在一场关于语言未来发展的非常激动人心的辩论中被抓住,现在我们要确保我们不要以抑制这些语言的方式添加它未来的可能性有时语言设计是一个非常长的游戏!“
来源:评论部分> https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/ 的
多年来我打开了这个问题并希望能够看到这个问题,我已经停止计算了多少次。
嗯,最后我们都欢欣鼓舞!微软将在他们即将发布的C#8版本中介绍这一点。所以不要这样做......
public static class IntExtensions
{
public static bool Even(this int value)
{
return value % 2 == 0;
}
}
我们终于可以这样做......
public extension IntExtension extends int
{
public bool Even => this % 2 == 0;
}
正如@Psyonity所提到的,您可以使用conditionalWeakTable向现有对象添加属性。结合动态ExpandoObject,您可以在几行中实现动态扩展属性:
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#extend class
并创建了一个更动态的版本:
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;
}
}
它可能会得到很多改进(命名,动态而不是字符串),我目前在CF 3.5中使用它和hacky ConditionalWeakTable( https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4 )