Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 静态只读变量初始化_C#_Static_Static Members - Fatal编程技术网

C# 静态只读变量初始化

C# 静态只读变量初始化,c#,static,static-members,C#,Static,Static Members,我有一些字典对象在应用程序生命周期内不会更改。我计划使用静态只读变量,任何人都可以提供以下几点的输入 直接初始化为静态只读属性与使用私有只读静态变量备份GET运算符的静态属性之间的区别 使用它们是否有任何风险,正如我在网上读到的,不使用公共静态变量。这是否适用于这种情况 由于作为字段,它们不能在静态构造函数运行后更改,因此从不变性和线程安全性的角度来看,没有理由使用静态只读属性包装它们 但是,请注意,有时需要字段上的属性-数据绑定是一个例子,反射的使用也是一个例子(如果在其中一个字段上进行标准化

我有一些字典对象在应用程序生命周期内不会更改。我计划使用静态只读变量,任何人都可以提供以下几点的输入

  • 直接初始化为静态只读属性与使用私有只读静态变量备份GET运算符的静态属性之间的区别

  • 使用它们是否有任何风险,正如我在网上读到的,不使用公共静态变量。这是否适用于这种情况


  • 由于作为字段,它们不能在静态构造函数运行后更改,因此从不变性和线程安全性的角度来看,没有理由使用静态只读属性包装它们


    但是,请注意,有时需要字段上的属性-数据绑定是一个例子,反射的使用也是一个例子(如果在其中一个字段上进行标准化,可能会更容易)。

    我建议尽可能多地使用属性。没有真正的性能惩罚,这是拥有公共字段最常见的原因。主要的好处是,您可以将自己与未来的实现细节更改隔离开来。如果使用字段,则每次编译的调用者都会绑定到访问字段

    我有一些字典对象在应用程序生命周期内不会更改

    当您将一个变量标记为Dictionary type
    readonly
    时,您将阻止用另一个Dictionary替换您指定的Dictionary。您不能将该词典设置为只读,因为一旦调用方获得该词典,他就可以自由地以任何方式进行更改,将其清除,或设置错误的值(毫无疑问,这是错误的)。如果需要使字典只读,请考虑借用只读包装器的实现。

    一般来说,在变量顶部添加属性,或拥有
    {get;private set;}
    自动属性,而不是
    readonly static
    的唯一优势是能够在setter中执行额外的检查,或在getter中添加一些代码(例如,收集访问统计信息或用于日志记录)。通过反射访问字段也有一些含义。看起来您并没有这样做,所以公开一个只读变量听起来很合适,并且不会带来额外的风险


    编辑:(关于使用反射)通过反射访问对象数据时,必须指定是访问属性
    Xyz
    还是访问字段
    Xyz
    。相反,当您编写C#程序时,您需要编写
    SomeClass.Xyz
    ,编译器会判断它是一个属性还是一个字段。如果创建一个公开字段
    Xyz
    ,然后决定用属性
    Xyz
    替换该字段的类,则只需重新编译直接引用
    Xyz
    的代码。但是,如果您编写的某些代码通过反射API访问
    Xyz
    ,则需要重写该代码,因为编译器将无法为您捕获更改。

    公共静态只读字段和公共静态属性之间没有什么区别。该属性在某种程度上确实保护了访问,但是如果您所做的只是返回值,那么这两者并没有什么区别

    // access between these two is almost identical
    public class Foo
    {
        public readonly static IDictionary<string, int> bar =
            new Dictionary<string, int>();
        public static IDictionary<string, int> Bar
        {
             get { return bar; }
        }
    }
    
    然后,如果确实需要从
    Foo.Bar
    添加或删除项,则可以创建函数来限制修改基础对象的方式

    public static void AddItem(string key, int value)
    { }
    public static void RemoveItem(string key)
    { }
    
    即使使用了
    ReadonlyDictionary
    实现,如果字典的
    TKey
    TValue
    是可变的,也可能会遇到修改问题

    总的来说,您看到的避免公共静态变量的原因在这里仍然成立。您引入了一个静态依赖项,每当重用使用
    Foo.Bar
    的代码时,该依赖项都会被拖拽。除非您静态访问的对象是不可变的,并且是只读的,否则可能会出现许多不可预见的副作用

    最好在合成根目录下创建对象的单个实例,并将其传递给需要依赖关系的对象

    public void CompRoot()
    {
         var bar = new ReadonlyDictionary(
             ... initialize with desired values ...
              // also this object is not in .NET but there
              // are many available on the net
         );
    
         var obj = new UsesBarDependency(bar);
    }
    
    public class UsesBarDependency
    {
         private readonly ReadonlyDictionary bar;
    
         public UsesBarDependency(ReadonlyDictionary bar)
         {
              if (bar == null)
                  throw new ArgumentNullException("bar");
              this.bar = bar;
         }
    
         public void Func()
         {
             // use to access the dependency
             this.bar 
             // over
             Foo.Bar
         }
     }
    

    这样做允许
    UsesBarDependency
    的用户向对象提供任何
    ReadonlyDictionary
    ,而不是被迫使用静态
    Foo.Bar
    依赖项。

    这很有帮助!我不理解这里的反射,Oded也提到了它。即使我可能不使用它,你能提供更多的信息吗?@Sundeep我编辑了答案,以扩展反思的含义。
    public void CompRoot()
    {
         var bar = new ReadonlyDictionary(
             ... initialize with desired values ...
              // also this object is not in .NET but there
              // are many available on the net
         );
    
         var obj = new UsesBarDependency(bar);
    }
    
    public class UsesBarDependency
    {
         private readonly ReadonlyDictionary bar;
    
         public UsesBarDependency(ReadonlyDictionary bar)
         {
              if (bar == null)
                  throw new ArgumentNullException("bar");
              this.bar = bar;
         }
    
         public void Func()
         {
             // use to access the dependency
             this.bar 
             // over
             Foo.Bar
         }
     }