views:

890

answers:

5
+3  Q: 

Static Indexers?

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:

static class ConfigurationManager {

        public object this[string name]{
            get{
                return 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) {
            DataSet ds = new DataSet();
            FileStream configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
            ds.ReadXml(configFile);

            if (ds.Tables["config"] == null) {
                ds.Tables.Add("config");
            }

            DataTable 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) {
            DataSet ds = new DataSet();
            FileStream configFile = new FileStream("./config.xml", FileMode.OpenOrCreate);
            ds.ReadXml(configFile);
            configFile.Close();


            if (ds.Tables["config"] == null) {
                return null;
            }

            DataTable 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?

+1  A: 

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):

class ConfigurationManager
{
  //private constructor
  ConfigurationManager() {}
  //singleton instance
  public static ConfigurationManager singleton;
  //indexer
  object this[string name] { ... etc ... }
}
ChrisW
Ah, thank you, I hadn't thought of that!
Malfist
+4  A: 

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 use this 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:


    public class Utilities
    {
        static ConfigurationManager _configurationManager = new ConfigurationManager();
        public static ConfigurationManager ConfigurationManager
        {
            get
            {
                return _configurationManager;
            }
        }
    }

    public class ConfigurationManager
    {
        public object this[string value]
        {
            get
            {
                return new object();
            }
            set
            {
                // set something
            }
        }
    }

Now you can call Utilities.ConfigurationManager["someKey"] using indexer notation.

Juliet
But why does the indexer have to use 'this'? It doesn't have to access instance data
Malfist
+1 for Malfist's comment. Just because it uses "this" for an instance indexer doesn't mean they couldn't come up with other syntax.
Jon Skeet
A: 

Related question here.

bruno conde
Not really, I know that they are not supported. I just wanted to know why.
Malfist
+4  A: 

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.

Jon Skeet
Intermediate Language - sort of assembly language for .NET.
Jon Skeet
A: 

Yet another workaround:

static class ConfigurationManager
{
    public sealed class ConfigurationPropertyIndexer
    {
        public object this[string name]
        {
            get { return ConfigurationManager.getProperty(name); }
            set { ConfigurationManager.editProperty(name, value); }
        }
    }

    private static ConfigurationPropertyIndexer Indexer;

    public static ConfigurationPropertyIndexer Properties
    {
        get { return Indexer ?? (Indexer = new ConfigurationPropertyIndexer()); }
    }

    ...

}

Usage:

ConfigurationManager.Properties["ConnectionString"] = "...";
George Chakhidze