通过静态或公共构造函数进行数据初始化

本文关键字:数据 初始化 构造函数 静态 | 更新日期: 2023-09-27 17:53:46

我想知道在静态构造函数而不是公共构造函数上初始化数据是否有缺点。我假设前两个代码狙击手也是这样做的。

下面的一个简短的例子

    class Test
    {
        private readonly static Dictionary<string, string> languages = 
            new Dictionary<string,string>()
            {
                {"de-CH", "Language.German".Translate()},
                {"fr-CH", "Language.French".Translate()},
                {"it-CH", "Language.Italian".Translate()}
            };
    }         

    class Test
    {
            private readonly static Dictionary<string, string> languages = 
            new Dictionary<string,string>();
            static LanguageChangeFragment()
            {
                languages.Add("de-CH", "Language.German".Translate());
                languages.Add("fr-CH", "Language.French".Translate());
                languages.Add("it-CH", "Language.Italian".Translate());
            }
    }

或使用公共构造函数

    class Test
    {
            private readonly Dictionary<string, string> languages = 
                    new Dictionary<string,string>();
            public LanguageChangeFragment()
            {
                languages.Add("de-CH", "Language.German".Translate());
                languages.Add("fr-CH", "Language.French".Translate());
                languages.Add("it-CH", "Language.Italian".Translate());
            }
    }
编辑:

在最后一个代码中删除了静态,这样当创建一个新的Test即时

通过静态或公共构造函数进行数据初始化

时就不会抛出异常

使用公共构造函数的主要问题是每次创建类Test的对象时都会执行普通的公共构造函数。这将导致每次创建Test实例时,静态languages字典都会增长。然而,在本例中,Test的第二个实例将抛出ArgumentException,因为字典要求所有键都是唯一的。

至于使用静态构造函数初始化或声明静态成员的选项,编译后的代码非常相似,因为第一次声明Test类型的变量时,该代码将运行并填充字典。

请记住,静态构造函数将在初始化所有静态成员后运行。

编辑

在上一个示例中,问题被更新为使字典成为实例成员。

现在这些例子之间的主要区别在于内存和适应性的使用。如果有一个字典实例是Test的每个实例的成员,那么大量的实例将使用更多的内存。这可能是这里所需要的,特别是如果Test的实例可能需要调整字典的内容,但不影响其他实例。如果字典在Test的所有实例中总是包含相同的元素,那么将字典设置为静态是有意义的——并让所有实例在内存中共享相同的字典。

我认为首先你必须了解每一种的特点。

从MSDN:

静态构造函数有以下属性:

    静态构造函数不接受访问修饰符,也没有参数。
  • 在创建第一个实例或引用任何静态成员之前,自动调用静态构造函数来初始化类。静态构造函数不能直接调用。用户无法控制静态构造函数何时在程序中执行。
  • 静态构造函数的典型用法是当类使用日志文件时,构造函数用于向该文件写入条目。静态构造函数在为非托管代码创建包装类时也很有用,因为构造函数可以调用LoadLibrary方法。

所以只要想想上面的,问自己很多问题,例如:

  • 初始化这个构造函数代价高吗?如果是这样,也许我需要控制何时初始化,这是静态构造函数无法做到的。
  • 我需要通过多个线程访问这个对象吗?如果是这样,那么使用普通的公共构造函数就会遇到麻烦。非托管代码也一样。