C#有扩展属性吗?

C#有扩展属性吗? git

例如,我能够向DateTimeFormatInfo添加一个名为ShortDateLongTimeFormat的扩展属性,它将返回ShortDatePattern + " " + LongTimePattern吗? github


#1楼

目前,Roslyn编译器仍然不支持开箱即用......

到目前为止,扩展属性被认为不足以包含在之前版本的C#标准中。 C#7C#8.0已将此视为提案冠军,但还没有发布,最重要的是由于即便已经有实施,他们也但愿从一开始就作到正确。 dom

但它会......

C#7工做列表中有一个扩展成员项,所以可能在不久的未来支持它。 扩展属性的当前状态能够在相关项下的Github上找到。 ui

然而,有一个更有但愿的主题是“扩展一切” ,重点是特别是属性和静态类甚至字段。 this

此外,您可使用解决方法

本文所述 ,您可使用TypeDescriptor功能在运行时将属性附加到对象实例。 可是,它没有使用标准属性的语法。
它与语法糖略有不一样,增长了定义扩展属性的可能性
string Data(this MyClass instance)做为扩展方法的别名
string GetData(this MyClass instance)由于它将数据存储到类中。 spa

我但愿C#7能提供全功能的扩展(属性和字段),可是在这一点上,只有时间会证实。 设计

并随意贡献,由于明天的软件未来自社区。 code

更新:2016年8月 orm

随着dotnet团队发布了C#7.0中的新内容以及Mads Torgensen的评论: xml

扩展属性:咱们有一个(辉煌!)实习生在夏天实施它们做为实验,以及其余类型的扩展成员。 咱们仍然对此感兴趣,但这是一个很大的变化,咱们须要确信这是值得的。

彷佛扩展属性和其余成员仍然是将来发布的Roslyn中的好选择,但可能不是7.0。

更新:2017年5月

扩展成员已被关闭做为扩展的全部问题的副本也被关闭。 主要的讨论其实是广义上的类型可扩展性。 此功能如今做为提案进行跟踪已从7.0里程碑中删除。

更新: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;

与部分类相似,但在不一样的程序集中编译为单独的类/类型。 请注意,您也能够经过这种方式添加静态成员和运算符。 如Mads Torgensen播客所述,扩展将不具备任何状态(所以它没法将私有实例成员添加到类中),这意味着您将没法添加连接到该实例的私有实例数据 。 为此调用的缘由是它意味着管理内部词典而且可能很难(内存管理等)。 为此,您仍然可使用前面描述的TypeDescriptor / ConditionalWeakTable技术和属性扩展,将其隐藏在一个不错的属性下。

语法仍然会发生变化,由于这意味着这个问题 。 例如, extends能够替换for一些可能感受更天然且更少与Java相关的extends

更新2018年12月 - 角色,扩展和静态接口成员

扩展一切都没有进入C#8.0,由于一些缺点被解释为这个GitHub票的结束。 所以,有一项改进设计的探索。 在这里 ,Mads Torgensen解释了什么是角色和扩展以及它们的区别:

角色容许在给定类型的特定值上实现接口。 扩展容许在特定代码区域内的给定类型的全部值上实现接口。

在两个用例中,能够看出先前提案的拆分。 扩展新语法以下:

public extension ULongEnumerable of ulong
{
    public IEnumerator<byte> GetEnumerator()
    {
        for (int i = sizeof(ulong); i > 0; i--)
        {
            yield return unchecked((byte)(this >> (i-1)*8));
        }
    }
}

而后你就能够这样作:

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; }
}

int上添加扩展属性并将int视为IMonoid<int>

public extension IntMonoid of int : IMonoid<int>
{
    public static int Zero => 0;
}

#2楼

由于我最近须要这个,因此我查看了答案的来源:

c#经过添加属性来扩展类

并建立了一个更动态的版本:

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


#3楼

正如@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 &lt; 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

#4楼

更新(感谢@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;
}

资料来源: https//blog.ndepend.com/c-8-0-features-glimpse-future/


#5楼

不,它们不存在于C#3.0中,也不会在4.0中添加。 它位于C#的功能需求列表中,所以可能会在未来添加。

此时,您能够作的最好的是GetXXX样式扩展方法。

相关文章
相关标签/搜索