属性构造函数如果只在反映属性时构造,为什么会如此受限?如此处所示,在您反射以获取属性值之前,不会调用属性构造函数。但是,您可能也知道,只能将编译时常量值传递给属性构造函数。为什么会这样?我想很多人宁愿做这样的事情:[MyAttribute(newMyClass(foo,bar,baz,jQuery)]而不是传递一个字符串(产生字符串类型的代码!),这些值变成字符串,然后依靠Regex尝试获取值而不是仅使用实际值而不是使用编译时警告/错误取决于可能抛出与类无关的异常,除了它调用的方法使用了一些错误类型属性。这有什么限制?属性是元数据的一部分。您需要能够在程序集中反映元数据,而无需在该程序集中运行代码。想象一下,例如,您正在编写一个需要读取属性的编译器从程序集中编译一些源代码。你真的想要加载和执行引用程序集中的代码吗?你是在要求编译器编写者编写一个可以在编译期间运行引用程序集中的任意代码的编译器吗?代码可能崩溃,或进入无限循环,或联系开发人员无权与之交谈的数据库?可怕场景的数量是巨大的,我们通过要求属性简单来消除它们。问题出在构造函数参数上。它们需要来自某个地方,它们不是由使用该属性的代码提供的。在通过调用其构造函数创建属性对象时,它们必须由反射管道提供。它需要构造函数参数值。这从编译时开始,编译器解析属性并记录构造函数参数。它将这些参数值以二进制格式存储在程序集元数据中。问题是运行时需要一种高度标准化的方法来反序列化这些值,最好不依赖于通常用于反序列化/序列化数据的任何.NET类。因为不能保证这些类在运行时实际上可用,所以它们不会它不是像MicroFramework这样精简版的.NET。即使像BinaryFormatter类的二进制序列化一样常见的东西也很麻烦,请注意它如何要求类上的[Serializable]属性允许它完成它的工作。版本控制也是一个大问题,显然这样的序列化程序类不应该通过破坏旧程序集中的属性来更改。这是一个困难重重的地方,CLS设计者通过严格限制允许的属性构造函数类型解决了这个问题。剩下的不多了,只有简单的值类型,字符串,它们的简单一维数组,Type。反序列化它们从来没有问题,因为它们的二进制表示很简单。非常严格,但属性仍然可以非常有表现力。最终的回退是在运行时使用字符串并在构造函数中解码该字符串。创建MyClass的对象不是问题,您可以在属性构造函数中完成。您必须将此构造函数所需的参数编码为属性的属性。关于为什么只能使用常量来表示属性,最正确的答案可能是因为C#/BCL设计团队没有判断是否支持任何其他重要的东西(即不值得付出努力)。构建时,C#编译器将实例化您放入代码中的属性并将它们序列化,以便它们可以存储在生成的程序集中。确保可以快速可靠地检索属性比支持更复杂的场景更重要。此外,由于某些属性属性值错误而导致失败的代码比某些框架内部反序列化错误更容易调试。考虑一下如果MyClass的类定义是在外部程序集中定义的会发生什么——编译并嵌入一个版本,然后更新MyClass的类定义并运行您的应用程序:砰!另一方面,DateTime实例不是非常令人沮丧的常量。有什么限制?你不可能做你所描述的事情的原因可能不是由任何限制引起的,但这纯粹是一种语言设计决定。基本上,在设计一种语言时,他们会说“这应该是可能的,但不是这样的”。如果他们真的希望这成为可能,那么就会考虑“限制”,这是可能的。我不知道这个决定背后的具体原因。/.../使用这些值传递一个字符串(产生字符串类型的代码!),成为一个字符串,然后依靠Regex尝试获取值而不是仅仅使用实际值/.../我已经处于类似的情况。有时我想使用带有lambda表达式的属性来实现某些功能。但是c#毕竟不是函数式语言,如果我用非函数式的方式写代码,就不需要这些属性了。简而言之,我是这样想的:如果我想以函数式的方式开发它,我应该使用像f#这样的函数式语言。现在我使用c#并以非功能性方式进行,然后我不需要这些属性。也许您应该重新考虑您的设计,而不是像现在这样使用属性。更新1:我声称c#不是函数式语言,但这是一种主观意见,并且没有“函数式语言”的严格定义。我同意AdamWright的观点,“/../所以我不会在一般性讨论中将C#用作功能-它充其量是多范式,具有一些功能。”为什么C#是一门功能性编程语言?更新2:我发现JonSkeet的这篇文章:https://stackoverflow.com/a/294259/1105687认为不允许使用通用属性类型,但这种情况下的推理可能相似:EricLippert的回答(转述):没有特别的原因,除了避免语言和编译器的复杂性,对于没有增加太多价值的用例。以上是C#学习教程:属性构造函数如果只在反映属性时构造,为什么会受到如此限制?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
