C# 理解c语言中的属性#

C# 理解c语言中的属性#,c#,attributes,C#,Attributes,我在研究attributes using System; public class HelpAttribute : Attribute { public HelpAttribute(String Descrition_in) { this.description = Description_in; } protected String description; public String Description {

我在研究
attributes

using System;
public class HelpAttribute : Attribute
{
    public HelpAttribute(String Descrition_in)
    {
        this.description = Description_in;
    }
    protected String description;
    public String Description 
    {
        get 
        {
            return this.description;

        }            
    }    
}
[Help("this is a do-nothing class")]
public class AnyClass
{
}
我的疑问是,当使用
这个
关键字时。 我们知道,
这个
指的是当前对象。 我看不到任何正在创建的对象

构造函数如何在这里真正工作

我看不到任何正在创建的对象

嗯,有。当您使用反射从
AnyClass
请求属性时,它将使用指定参数创建属性的新实例

实际上,该属性将像其他任何类一样创建,只是指定属性的语法不同

请注意,
AnyClass
的构造函数不会自动调用该属性

Type t = typeof(AnyClass);
HelpAttribute[] attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
                              .Cast<HelpAttribute>()
                              .ToArray(); // on this line the attribute is instantiated

Console.WriteLine(attributes.FirstOrDefault()?.Description);
Type t=typeof(AnyClass);
HelpAttribute[]attributes=t.GetCustomAttributes(typeof(HelpAttribute),true)
.Cast()
.ToArray();//在这一行中,属性被实例化
Console.WriteLine(attributes.FirstOrDefault()?.Description);
我看不到任何正在创建的对象

嗯,有。当您使用反射从
AnyClass
请求属性时,它将使用指定参数创建属性的新实例

实际上,该属性将像其他任何类一样创建,只是指定属性的语法不同

请注意,
AnyClass
的构造函数不会自动调用该属性

Type t = typeof(AnyClass);
HelpAttribute[] attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
                              .Cast<HelpAttribute>()
                              .ToArray(); // on this line the attribute is instantiated

Console.WriteLine(attributes.FirstOrDefault()?.Description);
Type t=typeof(AnyClass);
HelpAttribute[]attributes=t.GetCustomAttributes(typeof(HelpAttribute),true)
.Cast()
.ToArray();//在这一行中,属性被实例化
Console.WriteLine(attributes.FirstOrDefault()?.Description);

我喜欢已经给出的答案,只想在这里多加一点;不要将此标记为答案,如果需要,请将其用作帮助工具

属性没有成为类的一部分,它只是与类绑定。换句话说,任何使用
AnyClass
的人都不会关心或知道
HelpAttribute
,除非他们特别想/需要知道;当他们这样做时,他们会使用Patrick答案中列出的代码来获取信息

一个常见的问题是为什么使用它们以及如何正确使用它们。请记住,属性并不真的修改属性所包含的任何现有对象,而是用于编译和其他关心使用属性的对象。我将发布一个示例

注意:此示例仅用于教育目的。

在本例中,请注意,有两种方法调用worker。第一个运行worker,而不关心属性,第二个按自定义
PriorityAttribute
命令worker。另外,我很抱歉这是一个文件,这不是理想的。我这样做只是为了更容易在这里发布。不过,你可以复制并粘贴到控制台应用程序,它应该运行得很好。我正在使用VS2017、.NET 4.7.1和C#7.2(如果有必要的话)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static System.Console;
namespace ConsoleApp1
{
    class Program
    {
        public const int MaxNumberOfTasks = 10;
        private static readonly Random Random = new Random();

        static void Main(string[] args)
        {
            var workers = new List<IWorker>(MaxNumberOfTasks);

            for (var i = 0; i < MaxNumberOfTasks; i++)
                workers.Add(GetRandomWorker());

            WriteLine("Random Priority Workers\n");
            RunWorkersAsync(workers).Wait();

            WriteLine("\nSet Priority Workers\n");
            RunWorkersByPriorityAsync(workers).Wait();

            WriteLine("\nWork Complete\n");
            Read();
        }

        private static async Task RunWorkersAsync(List<IWorker> workers)
        {
            foreach (var worker in workers)
                await worker.DoWork();
        }

        private static async Task RunWorkersByPriorityAsync(List<IWorker> workers)
        {
            var highWorkers = new List<IWorker>();
            var mediumWorkers = new List<IWorker>();
            var lowWorkers = new List<IWorker>();

            foreach (var worker in workers)
            {
                var priorityAttribute = (PriorityAttribute)worker.GetType().GetCustomAttributes(typeof(PriorityAttribute), false).FirstOrDefault();
                if (priorityAttribute != null)
                {
                    switch (priorityAttribute.Priority)
                    {
                        case Priority.High:
                            highWorkers.Add(worker);
                            break;
                        case Priority.Medium:
                            mediumWorkers.Add(worker);
                            break;
                        case Priority.Low:
                        default:
                            lowWorkers.Add(worker);
                            break;
                    }
                }
                else
                {
                    lowWorkers.Add(worker);
                }
            }

            await RunWorkersAsync(highWorkers);
            await RunWorkersAsync(mediumWorkers);
            await RunWorkersAsync(lowWorkers);
        }

        private static IWorker GetRandomWorker()
        {
            var randomNumber = Random.Next(0, 3);
            switch (randomNumber)
            {
                case 0:
                    return new HighLevelWorker();
                case 1:
                    return new MediumLevelWorker();
                case 2:
                default:
                    return new LowLevelWorker();
            }
        }
    }

    public interface IWorker
    {
        Task DoWork();
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class PriorityAttribute : Attribute
    {
        public PriorityAttribute(Priority priority) => Priority = priority;
        public Priority Priority { get; }
    }

    public enum Priority
    {
        Low,
        Medium,
        High
    }

    [Priority(Priority.High)]
    public class HighLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(HighLevelWorker)} complete.");
        }
    }

    [Priority(Priority.Medium)]
    public class MediumLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(MediumLevelWorker)} complete.");
        }
    }

    [Priority(Priority.Low)]
    public class LowLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(LowLevelWorker)} complete.");
        }
    }
}

要从中吸取的东西。所有worker对象都执行完全相同的操作;它们的名称不同,但代码相同,实现相同的接口;唯一的区别是应用于每个属性的
PriorityAttribute
。您可以删除该属性,并且
RunWorkersAsync
runworkerbyprioritysync
任务将执行相同的操作。此外,如果更改任何属性的优先级,您将注意到无论类的名称如何,优先级都会随之改变。换句话说,我们可以使用或不使用优先级进行操作,也可以在需要时修改优先级(虽然在本例中,通过命名进行修改没有意义;但这同样只是出于教育目的。)

我喜欢已经给出的答案,只想在其中添加一点额外的内容;不要将此标记为答案,如果需要,请将其用作帮助工具

属性没有成为类的一部分,它只是与类绑定。换句话说,任何使用
AnyClass
的人都不会关心或知道
HelpAttribute
,除非他们特别想/需要知道;当他们这样做时,他们会使用Patrick答案中列出的代码来获取信息

一个常见的问题是为什么使用它们以及如何正确使用它们。请记住,属性并不真的修改属性所包含的任何现有对象,而是用于编译和其他关心使用属性的对象。我将发布一个示例

注意:此示例仅用于教育目的。

在本例中,请注意,有两种方法调用worker。第一个运行worker,而不关心属性,第二个按自定义
PriorityAttribute
命令worker。另外,我很抱歉这是一个文件,这不是理想的。我这样做只是为了更容易在这里发布。不过,你可以复制并粘贴到控制台应用程序,它应该运行得很好。我正在使用VS2017、.NET 4.7.1和C#7.2(如果有必要的话)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static System.Console;
namespace ConsoleApp1
{
    class Program
    {
        public const int MaxNumberOfTasks = 10;
        private static readonly Random Random = new Random();

        static void Main(string[] args)
        {
            var workers = new List<IWorker>(MaxNumberOfTasks);

            for (var i = 0; i < MaxNumberOfTasks; i++)
                workers.Add(GetRandomWorker());

            WriteLine("Random Priority Workers\n");
            RunWorkersAsync(workers).Wait();

            WriteLine("\nSet Priority Workers\n");
            RunWorkersByPriorityAsync(workers).Wait();

            WriteLine("\nWork Complete\n");
            Read();
        }

        private static async Task RunWorkersAsync(List<IWorker> workers)
        {
            foreach (var worker in workers)
                await worker.DoWork();
        }

        private static async Task RunWorkersByPriorityAsync(List<IWorker> workers)
        {
            var highWorkers = new List<IWorker>();
            var mediumWorkers = new List<IWorker>();
            var lowWorkers = new List<IWorker>();

            foreach (var worker in workers)
            {
                var priorityAttribute = (PriorityAttribute)worker.GetType().GetCustomAttributes(typeof(PriorityAttribute), false).FirstOrDefault();
                if (priorityAttribute != null)
                {
                    switch (priorityAttribute.Priority)
                    {
                        case Priority.High:
                            highWorkers.Add(worker);
                            break;
                        case Priority.Medium:
                            mediumWorkers.Add(worker);
                            break;
                        case Priority.Low:
                        default:
                            lowWorkers.Add(worker);
                            break;
                    }
                }
                else
                {
                    lowWorkers.Add(worker);
                }
            }

            await RunWorkersAsync(highWorkers);
            await RunWorkersAsync(mediumWorkers);
            await RunWorkersAsync(lowWorkers);
        }

        private static IWorker GetRandomWorker()
        {
            var randomNumber = Random.Next(0, 3);
            switch (randomNumber)
            {
                case 0:
                    return new HighLevelWorker();
                case 1:
                    return new MediumLevelWorker();
                case 2:
                default:
                    return new LowLevelWorker();
            }
        }
    }

    public interface IWorker
    {
        Task DoWork();
    }

    [AttributeUsage(AttributeTargets.Class)]
    public class PriorityAttribute : Attribute
    {
        public PriorityAttribute(Priority priority) => Priority = priority;
        public Priority Priority { get; }
    }

    public enum Priority
    {
        Low,
        Medium,
        High
    }

    [Priority(Priority.High)]
    public class HighLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(HighLevelWorker)} complete.");
        }
    }

    [Priority(Priority.Medium)]
    public class MediumLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(MediumLevelWorker)} complete.");
        }
    }

    [Priority(Priority.Low)]
    public class LowLevelWorker : IWorker
    {
        public async Task DoWork()
        {
            await Task.Delay(200);
            WriteLine($"{nameof(LowLevelWorker)} complete.");
        }
    }
}
要从中吸取的东西。所有worker对象都执行完全相同的操作;它们的名称不同,但代码相同,实现相同的接口;唯一的区别是应用于每个属性的
PriorityAttribute
。您可以删除该属性,并且
RunWorkersAsync
runworkerbyprioritysync
任务将执行相同的操作。此外,如果更改任何属性的优先级,您将注意到无论类的名称如何,优先级都会随之改变。换句话说,我们可以使用或不使用优先级进行操作,也可以在需要时修改优先级(尽管在本例中,通过命名进行修改是没有意义的;但这同样是错误的)