C#是否具有扩展属性?
C#是否具有扩展属性 例如,我可以为C#是否具有扩展属性?,c#,properties,extension-methods,C#,Properties,Extension Methods,C#是否具有扩展属性 例如,我可以为DateTimeFormatInfo添加一个名为ShortDateLongTimeFormat的扩展属性,该属性将返回ShortDatePattern+“”+longtimeptern?否它们在C#3.0中不存在,也不会在4.0中添加。它在C#的功能需求列表中,因此可能会在将来添加 在这一点上,您可以做的最好的事情是GetXXX风格的扩展方法 不,它们不存在 我知道C#团队曾经考虑过它们(或者至少Eric Lippert考虑过)——以及扩展构造函数和操作符(这
DateTimeFormatInfo
添加一个名为ShortDateLongTimeFormat
的扩展属性,该属性将返回ShortDatePattern+“”+longtimeptern
?否它们在C#3.0中不存在,也不会在4.0中添加。它在C#的功能需求列表中,因此可能会在将来添加
在这一点上,您可以做的最好的事情是GetXXX风格的扩展方法 不,它们不存在
我知道C#团队曾经考虑过它们(或者至少Eric Lippert考虑过)——以及扩展构造函数和操作符(这些可能需要一段时间才能让你了解,但很酷……),但是,我没有看到任何证据表明它们将成为C#4的一部分
编辑:它们没有出现在C#5中,截至2014年7月,看起来也不会出现在C#6中 ,微软C#编译器团队的主要开发人员,直到2012年11月,在2009年10月的博客中提到了这一点:
TypeDescriptor
功能在运行时将属性附加到对象实例。但是,它没有使用标准属性的语法。它有点不同于仅仅添加一个扩展属性的可能性,例如定义一个扩展属性
string Data(此MyClass实例)
,作为扩展方法string GetData(此MyClass实例)
的别名,因为它将数据存储到类中
我希望C#7将提供一个全功能的扩展,包括所有内容(属性和字段),但是在这一点上,只有时间才能证明这一点
明天的软件将来自社区,请随意贡献
更新日期:2016年8月
正如dotnet团队发表的评论:
扩展属性:我们有一个(非常棒的!)实习生来实现它们
夏天作为一个实验,伴随着其他种类的延伸
成员。我们仍然对此感兴趣,但这是一个很大的变化,我们
需要自信,相信这是值得的
扩展属性和其他成员似乎仍然是Roslyn未来版本中很好的候选对象,但可能不是7.0版本
更新日期:2017年5月
已关闭,其副本也已关闭。
实际上,主要讨论的是广义上的类型可扩展性。
该功能现在已被跟踪,并已从中删除
更新:2017年8月-C#8.0建议功能
虽然它仍然只是一个建议的特性,但我们现在对它的语法有了更清晰的了解。请记住,这也是扩展方法的新语法:
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;
那么你就可以做到这一点:
foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
WriteLine($"{e.Current:X}");
}
对于静态接口:
public interface IMonoid<T> where T : IMonoid<T>
{
static T operator +(T t1, T t2);
static T Zero { get; }
}
因为我最近需要这一点,所以我在以下内容中查看了答案的来源: 并创建了一个更具动态性的版本:
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;
}
}
公共静态类ObjectExtender
{
静态只读ConditionalWeakTable标志=新ConditionalWeakTable();
公共静态字符串GetFlags(此对象objectItem,字符串键)
{
返回Flags.GetOrCreateValue(objectItem).Single(x=>x.Key==Key).Value;
}
公共静态void SetFlags(此对象objectItem、字符串键、字符串值)
{
if(Flags.GetOrCreateValue(objectItem).Any(x=>x.Key==Key))
{
Flags.GetOrCreateValue(objectItem).Single(x=>x.Key==Key).Value=Value;
}
其他的
{
Flags.GetOrCreateValue(objectItem).Add(newStringObject())
{
键=键,
价值=价值
});
}
}
类stringObject
{
公共字符串密钥;
公共字符串值;
}
}
它可能会有很大的改进(命名、动态而不是字符串),我目前在CF 3.5中使用它,并使用一个hacky ConditionalWeakTable()正如@Psyonity所提到的,您可以使用ConditionalWeakTable向现有对象添加属性。结合dynamic ExpandooObject,您可以在几行中实现动态扩展属性:
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());
}
}
使用系统动态;
使用System.Runtime.CompilerServices;
命名空间扩展属性
{
///
///将属性动态关联到随机对象实例
///
///
///var jan=新员工(“jan”);
///
///jan.Age=24;//person对象的常规属性;
///jan.DynamicProperties().NumberOfDrinkingBuddies=27;//最初的作用域不是person对象;
///
///如果(1月年龄1月动态属性().饮酒伙伴数)
///Console.WriteLine(“简喝得太多”);
///
///
///如果您获得“Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create”,您应该引用Microsoft.CSharp
///
公共静态类对象扩展
{
///存储对象的扩展数据
私有静态ConditionalWeakTable extendedData=new ConditionalWeakTable();
///
///获取属性的动态集合作为
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;
}
}
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());
}
}
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
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;
}