C# 有扩展属性吗? [英] Does C# have extension properties?

查看:25
本文介绍了C# 有扩展属性吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C# 有扩展属性吗?

例如,我可以向 DateTimeFormatInfo 添加一个名为 ShortDateLongTimeFormat 的扩展属性,它会返回 ShortDatePattern + " " + LongTimePattern?

解决方案

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

直到现在,扩展属性的价值还不足以包含在以前版本的 C# 标准中.C# 7C# 8.0 已将此视为提案冠军,但尚未发布,最重要的是,即使已经有实现,他们也想实现从一开始.

但它会......

扩展成员C# 7 工作列表,因此可能会在不久的将来得到支持.扩展属性的当前状态可以在Github相关项下找到.

然而,还有一个更有前途的话题,那就是扩展一切"特别关注属性和静态类甚至字段.

此外,您可以使用一种解决方法

如本文章中所述,您可以使用TypeDescriptor 在运行时将属性附加到对象实例的能力.但是,它没有使用标准属性的语法.
它与语法糖有点不同,它增加了定义扩展属性的可能性,例如
string Data(this MyClass instance) 作为扩展方法的别名
stringGetData(this MyClass instance) 因为它将数据存储到类中.

我希望 C#7 将提供所有功能(属性和字段)的全功能扩展,但是在这一点上,只有时间会证明一切.

并随时做出贡献,因为明天的软件将来自社区.

更新:2016 年 8 月

当 dotnet 团队发布 C# 7.0 中的新增功能 以及来自 Mads Torgensen<的评论/a>:

<块引用>

扩展属性:我们有一个(太棒了!)实习生实现了它们夏天作为一个实验,以及其他类型的扩展成员.我们仍然对此感兴趣,但这是一个很大的变化,我们需要确信这是值得的.

似乎扩展属性和其他成员仍然是包含在 Roslyn 未来版本中的好候选,但可能不是 7.0 版本.

更新:2017 年 5 月

扩展成员已被关闭扩展所有问题也已关闭.主要讨论实际上是广义上的类型可扩展性.该功能现已在此处作为提案进行跟踪,并且已被从 7.0 里程碑.

更新:2017 年 8 月 - C# 8.0 提议的功能

虽然它仍然只是一个提议的功能,但我们现在对其语法有了更清晰的认识.请记住,这也将是扩展方法的新语法:

公共接口IEmployee{公共十进制薪水{得到;放;}}公开课员工{公共十进制薪水{得到;放;}}公共扩展 MyPersonExtension 扩展 Person : IEmployee{私有静态只读 ConditionalWeakTable_员工 =new ConditionalWeakTable();公共十进制工资{得到{//`this` 是 Person 的实例返回_employees.GetOrCreate(this).Salary;}放{员工员工=空;if (!_employees.TryGetValue(this, out employee){员工 = _employees.GetOrCreate(this);}员工工资 = 价值;}}}IEmployee person = new Person();var 薪水 = 人.薪水;

类似于部分类,但在不同的程序集中编译为单独的类/类型.请注意,您还可以通过这种方式添加静态成员和运算符.正如 Mads Torgensen 播客中所述, 扩展没有任何状态(因此它不能向类添加私有实例成员),这意味着您将无法添加链接到实例的私有实例数据.这样做的原因是它意味着管理内部字典,并且可能很困难(内存管理等).为此,您仍然可以使用前面描述的 TypeDescriptor/ConditionalWeakTable 技术和属性扩展,将其隐藏在一个不错的属性下.

语法仍可能发生变化,这意味着该问题.例如,extends 可以替换为 for,有些人可能会觉得更自然,与 Java 的相关性更少.

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

扩展所有内容 没有在 C# 8.0 中实现,因为在此结束时解释了一些缺点GitHub 票.于是,就有了改进设计的探索.此处,Mads Torgensen 解释了什么是角色和扩展以及如何它们不同:

<块引用>

角色允许在给定的特定值上实现接口类型.扩展允许在 a 的所有值上实现接口给定类型,在特定代码区域内.

可以在两个用例的先前提案的拆分中看到.扩展的新语法如下所示:

 ulong 的公共扩展 ULongEnumerable{公共 IEnumerator获取枚举器(){for (int i = sizeof(ulong); i > 0; i--){yield return unchecked((byte)(this >> (i-1)*8));}}}

那么你就可以这样做:

foreach(0x_3A_9E_F1_C5_DA_F7_30_16ul中的字节b){WriteLine($"{e.Current:X}");}

对于静态界面:

公共接口 IMonoid其中T:IMonoid T ;{静态 T 运算符 +(T t1, T t2);静态 T 零 { 得到;}}

int 上添加一个 extension 属性,并将 int 视为 IMonoid:

公共扩展 IntMonoid of int : IMonoid{公共静态整数零 =>0;}

Does C# have extension properties?

For example, can I add an extension property to DateTimeFormatInfo called ShortDateLongTimeFormat which would return ShortDatePattern + " " + LongTimePattern?

解决方案

For the moment it is still not supported out of the box by Roslyn compiler ...

Until now, the extension properties were not seen as valuable enough to be included in the previous versions of C# standard. C# 7 and C# 8.0 have seen this as proposal champion but it wasn't released yet, most of all because even if there is already an implementation, they want to make it right from the start.

But it will ...

There is an extension members item in the C# 7 work list so it may be supported in the near future. The current status of extension property can be found on Github under the related item.

However, there is an even more promising topic which is the "extend everything" with a focus on especially properties and static classes or even fields.

Moreover you can use a workaround

As specified in this article, you can use the TypeDescriptor capability to attach an attribute to an object instance at runtime. However, it is not using the syntax of the standard properties.
It's a little bit different from just syntactic sugar adding a possibility to define an extended property like
string Data(this MyClass instance) as an alias for extension method
string GetData(this MyClass instance) as it stores data into the class.

I hope that C#7 will provide a full featured extension everything (properties and fields), however on that point, only time will tell.

And feel free to contribute as the software of tomorrow will come from the community.

Update: August 2016

As dotnet team published what's new in C# 7.0 and from a comment of Mads Torgensen:

Extension properties: we had a (brilliant!) intern implement them over the summer as an experiment, along with other kinds of extension members. We remain interested in this, but it’s a big change and we need to feel confident that it’s worth it.

It seems that extension properties and other members, are still good candidates to be included in a future release of Roslyn, but maybe not the 7.0 one.

Update: May 2017

The extension members has been closed as duplicate of extension everything issue which is closed too. The main discussion was in fact about Type extensibility in a broad sense. The feature is now tracked here as a proposal and has been removed from 7.0 milestone.

Update: August, 2017 - C# 8.0 proposed feature

While it still remains only a proposed feature, we have now a clearer view of what would be its syntax. Keep in mind that this will be the new syntax for extension methods as well:

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;

Similar to partial classes, but compiled as a separate class/type in a different assembly. Note you will also be able to add static members and operators this way. As mentioned in Mads Torgensen podcast, the extension won't have any state (so it cannot add private instance members to the class) which means you won't be able to add private instance data linked to the instance. The reason invoked for that is it would imply to manage internally dictionaries and it could be difficult (memory management, etc...). For this, you can still use the TypeDescriptor/ConditionalWeakTable technique described earlier and with the property extension, hides it under a nice property.

Syntax is still subject to change as implies this issue. For example, extends could be replaced by for which some may feel more natural and less java related.

Update December 2018 - Roles, Extensions and static interface members

Extension everything didn't make it to C# 8.0, because of some of drawbacks explained as the end of this GitHub ticket. So, there was an exploration to improve the design. Here, Mads Torgensen explains what are roles and extensions and how they differs:

Roles allow interfaces to be implemented on specific values of a given type. Extensions allow interfaces to be implemented on all values of a given type, within a specific region of code.

It can be seen at a split of previous proposal in two use cases. The new syntax for extension would be like this:

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

then you would be able to do this:

foreach (byte b in 0x_3A_9E_F1_C5_DA_F7_30_16ul)
{
    WriteLine($"{e.Current:X}");
}

And for a static interface:

public interface IMonoid<T> where T : IMonoid<T>
{
    static T operator +(T t1, T t2);
    static T Zero { get; }
}

Add an extension property on int and treat the int as IMonoid<int>:

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

这篇关于C# 有扩展属性吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆