用于信息或导入外部函数的C#属性?

用于信息或导入外部函数的C#属性?,c#,C#,我对C#对属性的使用有点困惑。起初,我认为它只是通过使用。现在我发现它可以用来导入动态链接库及其函数。属性可以导入.exe文件和其他类型的文件吗 最后一个问题,对于每天在C#工作的程序员来说,您使用属性的次数是多少?除了扩展信息和导入dll之外,您还使用属性做其他任何事情吗?简单地说,属性只是附加到类或方法的元数据,从根本上说 但是,编译器会通读您的代码,并对执行此操作时遇到的特定属性执行特定操作,并将其硬编码到代码中。例如,当它在一个方法上找到一个符号时,它将把它解析为一个外部符号(同样,这是

我对C#对属性的使用有点困惑。起初,我认为它只是通过使用。现在我发现它可以用来导入动态链接库及其函数。属性可以导入.exe文件和其他类型的文件吗


最后一个问题,对于每天在C#工作的程序员来说,您使用属性的次数是多少?除了扩展信息和导入dll之外,您还使用属性做其他任何事情吗?

简单地说,属性只是附加到类或方法的元数据,从根本上说

但是,编译器会通读您的代码,并对执行此操作时遇到的特定属性执行特定操作,并将其硬编码到代码中。例如,当它在一个方法上找到一个符号时,它将把它解析为一个外部符号(同样,这是一个非常简单的解释)。 当它发现一个错误时,会发出一个弃用警告

您自己的属性(使用继承自
属性
基类的类)不会对默认编译器产生影响。但您(或其他库)也可以在运行时扫描它们,从而打开许多可能性,并引出第二个问题:

我通常用它们来做元编程。例如,设想一个自定义网络服务器处理特定格式的数据包,这些数据包在不同的类中实现。通过读取一个整数值来识别每个数据包格式。现在我需要找到正确的类来实例化该整数

  • 我可以使用switch..case或dictionary mapping integer->packet来实现这一点,我每次添加一个包时都会扩展它,但这很难看,因为每当我添加或删除一个包时,我必须接触可能远离实际包类的代码。如果服务器是在我的数据包以外的另一个程序集中实现的,我甚至可能不知道交换机或字典(模块化/可扩展性)
  • 相反,我创建了一个自定义的
    PacketAttribute
    ,通过该属性存储一个整数属性集,并用它装饰我的所有数据包类。服务器只需在启动时扫描我的程序集类型(通过反射),并自动构建整数->数据包对字典。当然,我可以在每次需要数据包时扫描我的程序集,但从性能角度看,这可能有点慢
有些API的属性更重,比如:将完整的请求URL映射到处理程序类中的方法,然后执行服务器代码。甚至URL参数也以这种方式映射到参数

调试器还可以使用属性。例如,使用装饰类可以在Visual Studio中检查类实例时为其提供显示的自定义字符串,该字符串具有特定格式,可以直接显示重要成员的值


您可以看到,如果使用得当,属性可能非常强大。这些评论提供了更多的参考资料!:)

要回答问题的第二部分,它们还可用于设置web应用程序中客户端和服务器端使用的验证和显示属性。例如:

[Display(Name = "Person's age")]
[Required(ErrorMessage = "Persons's age is required")]
[RangeCheck(13, 59, ErrorMessage = "The age must be between 13 and 59")]
 public int? PersonsAgeAtBooking { get; set; }
或装饰用于显示的枚举

public enum YesNoOnlyEnum
{
    [Description("Yes")]
    Yes = 1,
    [Description("No")]
    No = 2
}

还有许多其他用途。

我要补充的是,除了编译器识别的属性和自定义属性外,还有框架在运行时识别的属性,例如MVC使用的属性。很好的回答:只是添加-JIT还读取许多属性,许多BCL类型和流行库也是如此。属性很好<代码>[Yay]书签!我非常高兴在这里得到这个信息。我整夜都在做这件事,并且阅读了无数关于这个主题的教程;一个很好的例子是向库提供信息,例如告诉OEM列的名称,或者告诉序列化程序应该如何处理特定属性。或者告诉JIT永远不要内联某个特定的方法,等等,如果没有属性来修饰测试类和方法或将测试数据传递到测试中,就无法有效地进行单元测试。