Why are static indexers disallowed in C#? I see no reason why they should not be allowed and furthermore they could be very useful.
For example:
public static class ConfigurationManager
{
public object this[string name]
{
get => ConfigurationManager.getProperty(name);
set => ConfigurationManager.editProperty(name, value);
}
/// <summary>
/// This will write the value to the property. Will overwrite if the property is already there
/// </summary>
/// <param name="name">Name of the property</param>
/// <param name="value">Value to be wrote (calls ToString)</param>
public static void editProperty(string name, object value)
{
var ds = new DataSet();
var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
ds.ReadXml(configFile);
if (ds.Tables["config"] == null)
ds.Tables.Add("config");
var config = ds.Tables["config"];
if (config.Rows[0] == null)
config.Rows.Add(config.NewRow());
if (config.Columns[name] == null)
config.Columns.Add(name);
config.Rows[0][name] = value.ToString();
ds.WriteXml(configFile);
configFile.Close();
}
public static void addProperty(string name, object value) =>
ConfigurationManager.editProperty(name, value);
public static object getProperty(string name)
{
var ds = new DataSet();
var configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
ds.ReadXml(configFile);
configFile.Close();
if (ds.Tables["config"] == null) return null;
var config = ds.Tables["config"];
if (config.Rows[0] == null) return null;
if (config.Columns[name] == null) return null;
return config.Rows[0][name];
}
}
The above code would benefit greatly from a static indexer. However it won't compile because static indexers are not allowed. Why is this so?
Indexer notation requires a reference to
this
. Since static methods don't have an reference to a particular instance of the class, you can't usethis
with them, and consequently you can't use indexer notation on static methods.The solution to your problem is using a singleton pattern as follows:
Now you can call
Utilities.ConfigurationManager["someKey"]
using indexer notation.I believe it was considered not to be terribly useful. I think it's a shame too - an example I tend to use is Encoding, where Encoding.GetEncoding("foo") could be Encoding["Foo"]. I don't think it would come up very often, but aside from anything else it just feels a little inconsistent not to be available.
I would have to check, but I suspect it's available in IL already.
The reason is because it is quite hard to understand what exactly you are indexing with a static indexer.
You say that the code would benefit from a static indexer, but would it really? All it would do is change this:
Into this:
which does not make the code better in any way; it is not smaller by many lines of code, it isn't easier to write thanks to autocomplete and it is less clear, as it hides the fact that you are getting and setting something you call 'Property' and it actually forces the reader to go read the documentation on what exactly the indexer returns or sets, because it is in no way obvious that it is a property that you are indexing for, while with both:
You can read it out loud and immediately understand what the code does.
Remember that we want to write code that is easy (= fast) to understand, not code that is fast to write. Do not mistake the speed at which you can lay down the code with the speed at which you complete projects.
The this keyword refers to the current instance of the class. Static member functions do not have a this pointer. The this keyword can be used to access members from within constructors, instance methods, and instance accessors.(retrieved from msdn). Since this references an instance of the class it conflicts with the nature of static, since static isn't associated with an instance of the class.
One workaround would be the following which allows you to use the indexer against a private Dictionary so you only need to create a new instance and you access the static part.
This allows you to skip the whole accessing a member of the class and just create an instance of it and index it.
As a work-around, you can define an instance indexer on a singleton/static object (say that ConfigurationManager is a singleton, instead of being a static class):
With the newer constructs in C# 6, you might simplify the singleton pattern with a property expression body. For instance, I used the following shortcut which works nicely with code-lense:
It has the added benefit of being find-replace-able for upgrading older code and unifying your application settings access.