C# 静态只读变量初始化
我有一些字典对象在应用程序生命周期内不会更改。我计划使用静态只读变量,任何人都可以提供以下几点的输入C# 静态只读变量初始化,c#,static,static-members,C#,Static,Static Members,我有一些字典对象在应用程序生命周期内不会更改。我计划使用静态只读变量,任何人都可以提供以下几点的输入 直接初始化为静态只读属性与使用私有只读静态变量备份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
}
}