我有一些字典对象在应用程序的生命周期中不会改变。我打算使用静态只读变量,任何人都可以提供以下几点的输入。直接初始化为静态只读属性和静态特性与GET运营商之间静态只读变量初始化
差异备份与私人只读静态变量。
使用它们是否有任何风险,因为我在线阅读不使用public static变量。这是否适用于这种情况。
我有一些字典对象在应用程序的生命周期中不会改变。我打算使用静态只读变量,任何人都可以提供以下几点的输入。直接初始化为静态只读属性和静态特性与GET运营商之间静态只读变量初始化
差异备份与私人只读静态变量。
使用它们是否有任何风险,因为我在线阅读不使用public static变量。这是否适用于这种情况。
我有一个在应用程序生命周期并没有改变一些字典对象。
当您标记字典类型readonly
的变量时,会阻止替换您使用另一个字典分配的字典。你做不使该字典只读的,在这个意义上,只要呼叫者得到他的手在那本字典,他是免费的,他想,擦干净,或设置不正确的值的任何方式改变(由错误,毫无疑问)。如果您需要将Dictionary设置为只读,请考虑借用只读封装的实现from this answer。
一般来说,在变量顶部添加属性或者在{get;private set;}
自动属性上添加属性的优势在于您可以在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; }
}
}
你要碰到的问题是,即使该领域已被标记为readonly
它仍然是可变的。什么是阻止某人拨打Foo.Bar.Clear();
为了解决这个问题,您可以创建一个副本并将其返回,或者您可以使用只读字典实现。
public class Foo
{
private readonly static IDictionary<string, int> bar =
new Dictionary<string, int>();
public static IDictionary<string, int> Bar
{
// now any calls like Foo.Bar.Clear(); will not clear Foo.bar
get { return new Dictionary<string, int>(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提到的。尽管我可能不会使用它,请您提供更多信息。 – Sunny 2013-02-14 22:28:11
@Sundeep我编辑了答案,以扩大反思含义。 – dasblinkenlight 2013-02-14 22:38:49