Reputation: 4809
I have some dictionary objects which doesn't change during application life time. I am planning to use static readonly variables, could anyone provide inputs on below points.
Difference between initializing directly as static readonly properties and static properties with GET operator backed up with private readonly static variables.
Is there any risk using them as I have read online not to use public static variables. Does this apply for this situation.
Upvotes: 3
Views: 6631
Reputation: 5607
There is little difference between a public static readonly field and a public static property. The property does protect access to some extent, but if all you're doing is returning the value, the two don't really differ.
// 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; }
}
}
The issue you are going to run into is that even though the field has been marked as readonly
it is still mutable. What's to stop someone from calling Foo.Bar.Clear();
In order to resolve this, you could create a copy and return that, or you could find use a readonly dictionary implementation.
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); }
}
}
Then if you if you do need to add or remove items from Foo.Bar
you can create functions to limit how the underlying object is modified.
public static void AddItem(string key, int value)
{ }
public static void RemoveItem(string key)
{ }
Even if you use a ReadonlyDictionary
implementation, you may still run into issues with modification, if the TKey
or TValue
of the dictionary are mutable.
Overall those, the reasons you've seen to avoid the public static variables still hold true here. You are introducing a static dependency that will be dragged along whenever the code that uses Foo.Bar
is reused. Unless the object you are statically accessing is immutable as well as readonly, there are any number of unforeseen side effects that may occur.
You would be better off creating single instance of the object at your composition root and passing that around to the objects that need the dependency.
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
}
}
Doing so allows users of UsesBarDependency
to provide whatever ReadonlyDictionary
to the object instead of being forced to use the static Foo.Bar
dependency.
Upvotes: 1
Reputation: 726499
I have some dictionary objects which doesn't change during application life time.
When you mark a variable of Dictionary type readonly
, you prevent the replacement of the dictionary that you assign with another dictionary. You do not make that dictionary read-only, in the sense that as soon as a caller gets his hands on that dictionary, he is free to change in any way that he wants, wiping it clean, or setting incorrect values (by mistake, no doubt). If you need to make a Dictionary read-only, consider borrowing an implementation of a read-only wrapper from this answer.
In general, the only advantage of adding a property on top of a variable, or having a {get;private set;}
automatic property, over a readonly static
is your ability to perform additional checks in the setter, or adding some code in the getter (say, to collect access statistics or for logging). There are also implications to accessing the field through reflection. It does not look like you are doing any of that, so exposing a readonly variable sounds appropriate and does not present additional risks.
EDIT: (on using reflection) When you access object data through reflection, you must specify if you are accessing a property Xyz
or a field Xyz
. In contrast, when you write a C# program, you write SomeClass.Xyz
, and the compiler figures out if it's a property or a field for you. If you create a class that exposes a field Xyz
, and later decide to replace it with a property Xyz
, recompiling the code that refers to Xyz
directly is all it takes. However, if you wrote some code that accesses Xyz
by through the reflection API, that code would need to be rewritten, because the compiler would not be able to catch the change for you.
Upvotes: 4
Reputation: 20157
I recommend using properties as much as possible. There's no real performance penalty, which is the reason most often stated for having public fields. The primary benefit is that you insulate yourself against future implementation detail changes. If you go with the field, your compiled callers are tied to accessing to a field, every time.
Upvotes: 1
Reputation: 498972
Since, as fields, they cannot be changed after the static constructor has run, there is no reason in terms of immutability and thread safety in having static readonly properties wrapping them.
Note, however, that properties over fields are sometimes needed - data binding is one example, as is the use of reflection (where it may be easier if you standardize on one or the other).
Upvotes: 1