What's the best way to store a group of constants that my program uses?
我有我的程序使用的各种常量…string、int、double等……储存它们的最佳方法是什么?我不认为我需要一个Enum,因为数据的类型不同,我想手动设置每个值。我应该把它们都放在空教室里吗?还是有更好的方法?
您可能将它们放在静态类中,具有静态只读属性。
1 2 3 4
| public static class Routes
{
public static string SignUp =>"signup";
} |
- GRRR…比平局快40秒。)
- +1,但如果可以从资源文件中提取这些内容进行本地化,则更好。
- 似乎有点冗长-为什么不静态只读字符串?
- @只有当用户看到这个值时。
- 听起来不错。就像EmptySet所说的,这里是否有任何理由使用属性而不是静态只读字符串?
- 为什么是只读的而不是常量?您没有在运行时设置该值,因此不需要将其设置为只读。
- 我喜欢在智力上拥有物业图标。
- @丹尼尔A.怀特-洛尔
- const的问题是,任何针对const编译的程序集在编译它们自己时都会获取这些const的本地副本;因此,如果更改某个值,则还必须重新编译依赖于定义常量的程序集的所有程序集,因此使用只读路由通常更安全。属性而不是公共静态值使您能够在将来灵活地添加一些编程逻辑(如从本地化中读取),而无需将接口更改为常量值。
- 作为魔鬼的拥护者,我必须指出const的优势在于,您可以在切换的情况下使用它。
- 我亲自去了常量路由,但是声明了包含常量的类是内部的,这样它们就不能在程序集外部使用,并且消除了在其他程序集中无法更新它们的问题。当然,如果你真的需要他们在大会之外,那是没有帮助的。在没有显式更改类修饰符的情况下,其他人不能在程序集外部使用它们,这确实让我平静了一些。
- @arviman和您只能在属性中使用常量值,没有readonly可以这样做。
- 只需添加静态只读字段就可以通过反射进行更改,这可能是一个安全问题。参见stackoverflow.com/questions/12201063/…
- 不能在switch语句中使用这些"常量"。请参阅其他答案以获得更好的解决方案。
- 但我不能在switch case中使用这些常量。它的解决方案是什么?
对于常量,使用一个充满常量的类是可以的。如果它们会偶尔发生变化,我建议您在配置和configurationmanager类中使用appsettings。
当我有"常量"实际上是从appsettings或类似文件中拉入时,我仍然会有一个"常量"类来包装从配置管理器中读取的内容。在任何想要使用设定值的地方,使用Constants.SomeModule.Setting而不是直接使用ConfigurationManager.AppSettings["SomeModule/Setting"]总是更有意义的。
由于SomeModule很可能是常量文件中的嵌套类,因此可以轻松地使用依赖注入将SomeModule直接注入依赖它的类中。您甚至可以提取SomeModule之上的接口,然后在消费代码中创建对ISomeModuleConfiguration的依赖关系,这将允许您分离对常量文件的依赖关系,甚至可能使测试更容易,特别是如果这些设置来自appsettings,并使用config transforma更改它们因为这些设置是环境特定的。
- 只是为了增加一点:原因是当您构建时,从其他程序集使用的常量不会更新。这意味着,如果有assemblya和assemblyb,并且b使用a中的常量,则会复制该值,而不是引用该值,因此重新生成a不会更新b。这可能会导致奇怪的错误。
- @camilomartin有很多方法来处理这个问题,你的"常量"可以只是静态的读数来避免这个问题,或者如我所说,如果它们在一个蓝色的月亮上改变不止一次,就可以使用配置管理器。
- 是的,我只是说,这不仅仅是因为它是一种约定,你应该使用静态只读,而是因为它实际上可能是一种混淆的来源。此外,配置管理器的另一种选择是资源文件-您只需添加另一个资源文件,名称中包含语言代码,代码立即本地化。
- 问题是,当您从其他程序集引用此程序集时,必须将值复制到它们的配置文件中。
- @symbont您可以嵌入配置文件并将其从清单中读取(如果需要的话),以便作为第三方组件进行共享。
我喜欢做的是以下操作(但请务必从头到尾阅读以使用适当类型的常量):
1 2 3 4 5 6
| internal static class ColumnKeys
{
internal const string Date ="Date";
internal const string Value ="Value";
...
} |
读这个来了解为什么const可能不是你想要的。可能的常量类型有:
- const字段。如果将来值可能发生变化,则不要在程序集(public或protected之间使用,因为该值将在编译时在这些其他程序集中进行硬编码。如果更改该值,则其他程序集将使用旧值,直到重新编译它们。
- static readonly字段
- 无set的static财产
- 为什么在多个程序集之间使用readonly?
- 为什么静态只读对多个程序集比常量更有效?
- 常量值从源程序集复制到编译的代码中。这意味着,如果必须更改常量值,则必须根据新版本重新编译所有依赖程序集。使用静态只读更安全、更方便。
- const的好处是它们可以在交换机中使用
这是IMO的最佳方法。不需要属性或只读:
1 2 3 4
| public static class Constants
{
public const string SomeConstant ="Some value";
} |
- 如果要使用const,则只作为内部公开。不要公开常量(即使您认为程序集不会在组织外部使用)。此外,属性还为将来的扩展提供了编程灵活性,无需重新定义接口。
空静态类是合适的。考虑使用几个类,这样就可以得到一组好的相关常量,而不是一个巨大的globals.cs文件。
另外,对于一些int常量,考虑符号:
因为这允许将值视为标志。
- "考虑使用几个类,这样就可以得到一组好的相关常量,而不是一个巨大的globals.cs文件。"我认为这是最好的建议,这周围不是有一些设计模式吗?我不知道任何名字,是吗?
使用web.config或app.config的另一个投票。对于连接字符串等常量来说,配置文件是一个很好的位置。我不希望看到源代码来查看或修改这些类型的内容。从.config文件中读取这些常量的静态类可能是一个很好的折衷方案,因为它可以让应用程序像在代码中定义的那样访问这些资源,但仍然可以灵活地将它们放在易于查看/编辑的空间中。
- 连接字符串不是常量,而是一个设置。这可能是因为操作实际上也意味着设置,而不是常量,但我看不到任何证据。
- 我不同意。字符串文本是定义上的常量。在配置文件中更改字符串大致相当于在代码中更改它并重新编译;这会使它不是常量吗?我不这么认为。
- @大卫-不是真的。编译器不关心配置文件中的值——这是在运行时读取的。
- @飞利浦,我明白。我的观点是(响应乔恩·斯基特的评论)一个特定的连接字符串是一个常量,就像所有字符串文本一样。事实上,一个"常量"可以被改变——比如通过修改配置文件,让你的应用从所述配置文件中提取新的值,或者通过改变代码中需要重新编译/部署的文字——并不意味着它是一个"设置"。不管它的容器是什么,字符串本身都是常量。我理解并同意你的观点-这不是我说的。
- 根据我的经验,在不可预见的未来的某个时刻,你的"不变"价值需要改变,即使你认为它在一百万年内永远不会改变。我认为在.config文件中这样做要比更改源代码容易得多。一切最终都是一个背景。
- 当然。我认为这里的困惑在于我们试图区分"常量"和"设置",这并不像过去那样有用。
是的,用于存储常量的static class就可以了,除了与特定类型相关的常量。
- 这正是我想做的。我想让他们成为他们所在班级的成员。但我不想将它们添加到类中,因为常量的变化取决于我为之工作的公司。我还没有找到任何关于扩展常量或属性的信息。但我可能会放弃这个想法,因为我不希望它们在序列化这些类时显示为成员
我建议用静态只读的静态类。请在下面找到代码段:
1 2 3 4
| public static class CachedKeysManager
{
public static readonly string DistributorList ="distributorList";
} |
如果这些常量是影响应用程序行为的服务引用或开关,我会将它们设置为应用程序用户设置。这样,如果需要更改它们,就不必重新编译,您仍然可以通过静态属性类引用它们。
1
| Properties.Settings.Default.ServiceRef |