c#有扩展属性吗?
例如,我可以添加一个扩展属性的DateTimeFormatInfo称为ShortDateLongTimeFormat将返回ShortDatePattern + " " + LongTimePattern?
c#有扩展属性吗?
例如,我可以添加一个扩展属性的DateTimeFormatInfo称为ShortDateLongTimeFormat将返回ShortDatePattern + " " + LongTimePattern?
当前回答
正如@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# 3.0中不存在,也不会在4.0中添加。它在c#需要的特性列表中,所以将来可能会添加它。
在这一点上,你能做的最好的是GetXXX样式的扩展方法。
不,他们不存在。
我知道c#团队曾经考虑过它们(或者至少Eric Lippert曾经考虑过)——还有扩展构造函数和操作符(你可能需要一段时间才能理解它们,但是很酷……)然而,我还没有看到任何证据表明它们将成为c# 4的一部分。
编辑:它们没有出现在c# 5中,到2014年7月,看起来也不会出现在c# 6中。
Eric Lippert,微软c#编译器团队2012年11月的首席开发人员,在2009年10月写了一篇博文:
为什么没有扩展属性?-编程中的奇妙冒险
更新(感谢@chaos指出此更新):
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;
}
来源:https://blog.ndepend.com/c-8-0-features-glimpse-future/
因为我最近需要这个,我查看了答案的来源:
通过添加属性来扩展类
并创造了一个更动态的版本:
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中使用它和一个hack的ConditionalWeakTable (https://gist.github.com/Jan-WillemdeBruyn/db79dd6fdef7b9845e217958db98c4d4)
正如@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