57

一位同事刚刚在 C# 中创建了以下构造(示例代码已简化)。他的目标是缩短其余代码中所有预定义字符串的符号。

public struct PredefinedStrings
{
    public const string VeryLongName = "Very Long Name";
    public const string AnotherVeryLongName = "Another Very Long Name";
    public const string TheLastVeryLongName = "The Last Very Long Name";
}

public static void MethodThatUsesTheNames()
{
    Console.WriteLine(PredefinedStrings.VeryLongName);
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName);
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName);
}

尽管这对他来说似乎工作得很好,但我不禁想知道他是否应该使用静态类而不是结构,或者是否有更优雅的方式来实现这一点。

这样做的首选方法是什么?还请解释原因。

4

13 回答 13

53

有了这个struct解决方案,就没有什么可以阻止其他代码做的事情了new PredefinedStrings(),这不会做任何坏事,但它在语义上是允许的。使用静态类,编译器将禁止为您创建。不言而喻,静态类是在框架中提供常量的首选方式。

编辑添加,我说第二部分没有证据 - 我已经搜索并很快找到了System.Net.Mime.DispositionTypeNamesSystem.Net.WebRequestMethods.Http

于 2010-02-08T16:44:12.767 回答
32

我希望所有字符串都在资源文件中,而不是嵌入代码中——主要是出于国际化的原因。然后可以通过将值作为属性成员的静态类来访问它。

于 2010-02-08T16:46:12.323 回答
26

除了 a 之外static classstruct为什么不考虑使用resource文件作为常量字符串呢?这些可以很容易地访问SomeNamespace.ResourceName.KeyName,并且根据它们在项目中的位置可以在外部进行管理,而无需重新编译(如果需要)...

于 2010-02-08T16:47:57.140 回答
12

简单的经验法则:除非你别无选择,否则永远不要使用结构。

常量有几个缺点:

  • 只能使用简单类型(字符串、数字等)
  • 常量被注入到引用程序集中。如果你用常量重新编译程序集并且不重新编译使用常量的程序集,你会遇到麻烦

我会这样写你的代码(注意重命名重构):

public static class KnownNames
{
    public static readonly string VeryLong = "Very Long Name";
    public static readonly string AnotherVeryLong = "Another Very Long Name";
    public static readonly string TheLastVeryLong = "The Last Very Long Name";
}
于 2010-02-08T17:30:42.170 回答
6

这段代码在功能上没有任何问题。但从风格上讲,我同意静态类更好。静态类声明类型的意图是只保存静态/常量数据。

于 2010-02-08T16:45:22.793 回答
6

听起来您正在寻找资源文件 (.resx)。这是存储此类字符串的好地方,并且将您的字符串抽象为 .resx 将使您将来更容易本地化您的应用程序。http://msdn.microsoft.com/en-us/library/1ztca10y.aspx上的 MSDN 页面是了解更多信息的良好开端。

于 2010-02-08T16:51:17.477 回答
5

ETA:感谢Dennis19901:因为这些字符串是const,它们实际上不会占用任何空间。将struct仅消耗 1 个字节。

旧信息和破坏信息:不要忘记结构大小应为 16 字节左右的建议。给定一个 32 位系统,那里有 4 个 System.String 引用。如果字符串的数量会增加,我会说你最好使用静态类。

于 2010-02-08T17:04:13.910 回答
3

静态类似乎是最好的方法,因为它是最标准和最受期待的。我认为 struct/const 版本可能会更快,但经过一些测试后却不是。

这是我的快速测试的结果,包括长度、比较、连接、复制、indexOf 和子字符串。它在没有附加调试器的情况下在 .Net 4.0 版本下运行。

                                          .Net 3.0  .Net 4.0
static class with static read-only string:  0.217   0.364  seconds
static class with const            string:  0.211   0.361  seconds
struct       with static read-only string:  0.211   0.372  seconds
struct       with const            string:  0.214   0.371  seconds
Properties.Resources               string:  1.173   1.268  seconds

除了使用更慢的资源文件时,它们的性能都差不多。虽然 Properties.Resources 速度较慢,但​​它并未存储在可执行文件中,因此在某些情况下可能更合适。因此,我认为使用“静态类”或 Properties.Resources 存储字符串。

于 2014-12-27T20:58:32.407 回答
2

结构通常会被避免,除非它们符合此答案中详述的某些标准。

由于您的同事没有使用它来存储值,因此他应该使用类,而不是结构。

于 2015-06-26T21:19:59.987 回答
1

我认为静态更好,这是我的推理。如果这段代码存在于某个库中,而另一段代码使用了这个库,如果常量字段的值发生变化,那么不仅需要重新编译这个库(duh),而且你必须重新编译使用它的代码图书馆也是。这样做的原因是,编译器会在您引用它们的任何地方插入常量值。但是,如果您使用 static ,则不会遇到此问题,因为您引用的是field而不是value

于 2010-02-08T16:48:28.557 回答
0

在我的实践中,我们使用Dictionary<enumNameType, string>. 其中 enumNameType 是您可以拥有的不同类型的名称(在您的情况下)......这个字典被包装在一个静态类中并被缓存 - 我们只是在第一次使用它时创建它,然后返回相同的对象......

我希望这对你也有用!

于 2010-02-08T16:43:59.327 回答
0

我也将结构用于常量,但仅用于内部使用,不适用于公共 API。感觉很自然,因为枚举也转换为结构。

于 2010-02-08T16:49:01.803 回答
0

允许您创建一个旨在成为常量的新对象这一简单事实清楚地证明了不良做法(通常)。我说“通常”是因为 .NET 确实偶尔会使用这个概念,但原因尚不清楚。

当然,你总是可以做这样的事情:

public class Foo
{
    public struct Bar
    {
        public static double A = 100;

        public Bar(double a)
        {
            A = a;
        }
    }
}

从技术上讲,这确实证明了创建Bar; 但是,不能保证常量Bar永远相同(即使在单线程环境中)并且最终几乎没有用处。

于 2017-01-26T18:19:25.013 回答