在 C# 中实现全局常量的最佳方法是什么?
我有一个 Common 项目,在其中添加了 QueryStringNames 的公共常量。
我知道通常常量应该是内部常量或私有常量,但我在这里需要公共常量,因为我想允许全局访问查询字符串名称、会话密钥等。
我知道有 3 种解决方案,但全部都是他们有一个重要的问题。调用者程序集将包含我的常量的副本,这意味着如果我必须更改常量值,我将必须编译我的公共程序集和调用者程序集!
1) public const string ConstName = "a value";
2) public readonly string ConstName = "a value";
3) To be stored in a public resource file.
除了将它们存储在 web.config 文件(没有智能感知)中之外,在 C# 中定义公共常量的最佳方法是什么?
I have a Common project inside which I've added my public constants for QueryStringNames.
I know generally constants should be as internal or private but I'd need public constants here as I'd like to allow a global access to the query string names, session keys, etc.
There are 3 solutions that I know of but all of them have an important issue. The caller assembly would contain the copy of my constant which means if I have to change a constant value, I'll have to compile both my Common assembly and the caller assembly!
1) public const string ConstName = "a value";
2) public readonly string ConstName = "a value";
3) To be stored in a public resource file.
What would be the best approach to define public constants in C# apart from storing them in the web.config file (which doesn't have intellisense)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这取决于。如果它确实是一个不会改变的常量,即使在代码的未来版本中,那么
const
就可以了。否则使用static readonly
字段。const 将嵌入到调用程序集中,而使用 static readonly 时,调用程序集仅包含对该字段的引用。这意味着每当您更改值时,
const
都需要重新编译所有依赖代码,而public readonly
即使不重新编译调用程序集也会使用新值。如果您想将“常量”存储在配置文件中,但像 Intellisense 一样,您可以使用没有公共设置器的属性。然后在运行时从配置文件中填充它。但我认为配置值首先就不应该是静态的。对于配置值,我会使用某种类型的单例,最好是 IoC 变体,而不是 Class.Instance 变体。所以我只需定义一个如下所示的接口:
并且让需要此配置的类将其作为构造函数参数:
It depends. If it is truly a constant that won't change, even in future versions of your code, then
const
is fine. Else go with astatic readonly
field.A
const
will get embedded into the calling assembly, whereas withstatic readonly
the calling assembly only contains a reference to the field. This meansconst
requires recompilation of all dependent code whenever you change the value, whereaspublic readonly
uses the new value even without recompiling the calling assembly.If you want to store the "constant" in a config file, but like Intellisense, you can use a property with no public setter. And then fill it from the config file at runtime. But I'd argue that configuration values should not be
static
in the first place. For configuration values I'd use a singleton of some sort, preferably the IoC variation and not theClass.Instance
variation. So I'd just define an interface like the following:And have classes that need this config take it as a constructor parameter:
如果您认为要更改它并且担心必须编译它,那么为什么不在 Web 配置文件中使用 appSettings 呢?这就是它的用途。如果您确实需要智能感知,那么您可以在其中一个程序集中放置一个类,该程序集读取配置值并将其公开为属性以便于引用。如果它是敏感数据,那么我不会将其放入配置文件中,无论如何我都会编译它,因为您不想损害您的应用程序。
这是引用该值的类,它为您提供智能感知,将来能够轻松更改它,并且无需重新编译任何内容。
它可能不是您解决方案的答案,但它可能会给您一些其他想法。
If you think you'd be changing it and you're worried about having to compile it, then why not use appSettings in the web config file? That's what it's for. If you really need intellisense then you could just put a class in one of the assemblies that reads the config value and exposes it as a property for easier referencing. If it's sensitive data then I wouldn't put it in a config file, I would just compile it anyways since you don't want to compromise your application.
Here's the class to reference that value, which gives you intellisense, ability to change it easily in the future, and without having to recompile anything
It may not be the answer to your solution but it may give you some other ideas.
我不确定我是否完全理解这个问题...您正在寻求一种解决方案来存储一些全局变量,如果您更改它们,则不会导致重新编译引用这些全局变量的程序集?如果是这样,那么为什么不尝试考虑根据控制反转原则重新设计您的架构?想想“别打电话给我们,我们会打电话给你”的好莱坞原则。如果所有需要某些 const 的程序集都只是调用一个接口(它们拥有的),该接口公开具有它们所需值的属性,那么您就有一个实现这些接口的常量项目(通过引用这些项目,然后实现这些接口)那么当您更改常量的值时,这些项目将永远不需要重新编译。
我相信您无论如何都知道它们,但请阅读 SOLID原则,“D”是依赖倒置原则(控制反转)。我认为考虑到您的担忧(假设我正确理解了您),他们确实可以帮助您。
控制反转的示例可以简单如下:
MyService.dll :
MyConstants.dll :
因此 myconstants.dll 引用 myservice.dll,而不是相反(意味着 myservices 不需要重新编译)。然后引导代码(用于设置所有内容并注入依赖项)位于其他地方。
抱歉,如果我误解了您的意思,希望对您有所帮助!
I'm not sure if I understand the problem completely... you're asking for a solution to storing some global variables that won't cause recompiles to assemblies that reference those global variables if you change them? If so then why not try thinking about redesigning your architecture as per the Inversion of Control principle? Think "don't call us, we'll call you" the hollywood principle. If all the assemblies that require some const just call an interface (that they own) that exposes a property with the value they require, and then you have a project of constants that implement those interface (by referencing those projects and then implementing those interfaces) then those projects will never need recompilling when you change the value of the constants.
I'm sure you know them anyway but have a read up on the SOLID principles, "D" being the Dependency Inversion principle (Inversion of Control). I think given your concerns (assuming I've understood you right) they could really help you out.
An example of Inversion of Control could be as simple as:
MyService.dll :
MyConstants.dll :
So the myconstants.dll references the myservice.dll rather than the other way around (meaning myservices won't need recompiling). Then the bootstrapping code (to set it all up and inject dependencies) lives elsewhere.
Sorry if I misunderstood you, hope that helps though!
如果您正在激活 fxCop(Visual Studio 发行版中包含的代码分析工具),您可能会收到将常量更改为的建议:
If you are activating fxCop (code analysis tool included in Visual studio distribution), you may get sugestion to change constant to become:
在大多数情况下,我更喜欢第二个选项,因为它不会引起问题(通过将值复制到其他程序集)。速度可能比常数慢,但这种纳秒级的速度还相当不成熟。
I prefer the 2nd option in most case since it won't cause problem (by copy value to other assemblies). The speed may have a slower than constants but this kind of nano-second speed is pretty immature.
您可以使用 Cache 对象并在 Global.asax 中定义它们
You could use the Cache object and define them in Global.asax
如前所述,这不是同一个场景:
As said before, it's not the same scenario: