Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#是否具有扩展属性?_C#_Properties_Extension Methods - Fatal编程技术网

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考虑过)——以及扩展构造函数和操作符(这

C#是否具有扩展属性

例如,我可以为
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月的博客中提到了这一点:

目前,Roslyn编译器仍然不支持它。。。 直到现在,扩展属性的价值还不足以包含在以前版本的C#standard中C#7C#8.0将其视为提案冠军,但尚未发布,最重要的是,即使已经有了实施,他们也希望从一开始就做好

但它会。。。 中有一个项目,因此在不久的将来可能会支持它。可在上找到扩展属性的当前状态

然而,还有一个更具前景的主题,那就是关注属性和静态类,甚至字段

此外,您还可以使用变通方法 如本文所述,您可以使用
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 &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());
    }
}
使用系统动态;
使用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 &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());
    }
}
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;
}