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
任务将执行相同的操作。此外,如果更改任何属性的优先级,您将注意到无论类的名称如何,优先级都会随之改变。换句话说,我们可以使用或不使用优先级进行操作,也可以在需要时修改优先级(尽管在本例中,通过命名进行修改是没有意义的;但这同样是错误的)