Indicadores estáticos?

¿Por qué los indexadores estáticos no se permiten en C #? No veo ninguna razón por la cual no se les permita y, además, podrían ser muy útiles.

Por ejemplo:

public static class ConfigurationManager { public object this[string name] { get => ConfigurationManager.getProperty(name); set => ConfigurationManager.editProperty(name, value); } ///  /// This will write the value to the property. Will overwrite if the property is already there ///  /// Name of the property /// Value to be wrote (calls ToString) 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]; } } 

El código anterior se beneficiaría enormemente de un indexador estático. Sin embargo, no se comstackrá porque los indexadores estáticos no están permitidos. ¿Por qué esto es tan?

La notación del indexador requiere una referencia a this . Como los métodos estáticos no tienen una referencia a una instancia particular de la clase, no puede usar this con ellos y, por lo tanto, no puede usar la notación del indexador en métodos estáticos.

La solución a su problema es usar un patrón singleton de la siguiente manera:

 public class Utilities { private static ConfigurationManager _configurationManager = new ConfigurationManager(); public static ConfigurationManager ConfigurationManager => _configurationManager; } public class ConfigurationManager { public object this[string value] { get => new object(); set => // set something } } 

Ahora puede llamar a Utilities.ConfigurationManager["someKey"] usando la notación del indexador.

Creo que se consideró que no era terriblemente útil. También creo que es una lástima, un ejemplo que suelo usar es Encoding, donde Encoding.GetEncoding (“foo”) podría ser Encoding [“Foo”]. No creo que surja con mucha frecuencia, pero aparte de cualquier otra cosa, parece un poco inconsistente no estar disponible.

Tendría que verificarlo, pero sospecho que ya está disponible en IL.

Como solución temporal, puede definir un indizador de instancia en un objeto único / estático (digamos que ConfigurationManager es un singleton, en lugar de ser una clase estática):

 class ConfigurationManager { //private constructor ConfigurationManager() {} //singleton instance public static ConfigurationManager singleton; //indexer object this[string name] { ... etc ... } } 

Con las construcciones más nuevas en C # 6, puede simplificar el patrón de singleton con un cuerpo de expresión de propiedad. Por ejemplo, utilicé el siguiente atajo que funciona muy bien con code-lense:

 public static class Config { public static NameValueCollection Get => ConfigurationManager.AppSettings; } 

Tiene el beneficio adicional de ser find-replace-able para actualizar el código anterior y unificar el acceso a las configuraciones de la aplicación.

La razón es porque es bastante difícil entender qué exactamente está indexando con un indexador estático.

Usted dice que el código se beneficiaría de un indexador estático, pero ¿realmente lo haría? Todo lo que haría es cambiar esto:

 ConfigurationManager.editProperty(name, value); ... value = ConfigurationManager.getProperty(name) 

Dentro de esto:

 ConfigurationManager[name] = value ... value = ConfigurationManager[name] 

que no mejora el código de ninguna manera; no es más pequeño por muchas líneas de código, no es más fácil de escribir gracias a la función autocompletar y es menos claro, ya que oculta el hecho de que está obteniendo y configurando algo que llama ‘Propiedad’ y realmente obliga al lector a Lea la documentación sobre qué devuelve o establece exactamente el indexador, porque de ninguna manera es obvio que es una propiedad para la que está indexando, mientras que con ambos:

 ConfigurationManager.editProperty(name, value); ... value = ConfigurationManager.getProperty(name) 

Puede leerlo en voz alta e inmediatamente comprender lo que hace el código.

Recuerde que queremos escribir un código que sea fácil (= rápido) de comprender, no un código que sea rápido de escribir. No confunda la velocidad con la que puede establecer el código con la velocidad a la que completa los proyectos.

La palabra clave this se refiere a la instancia actual de la clase. Las funciones de miembro estático no tienen este puntero. La palabra clave this se puede usar para acceder a miembros desde dentro de constructores, métodos de instancia y accesadores de instancia. (Recuperado de msdn ). Como esto hace referencia a una instancia de la clase, entra en conflicto con la naturaleza de estática, ya que estática no está asociada con una instancia de la clase.

Una solución alternativa sería la siguiente que le permite usar el indexador contra un diccionario privado, por lo que solo necesita crear una nueva instancia y acceder a la parte estática.

  public class ConfigurationManager { public ConfigurationManager() { // TODO: Complete member initialization } public object this[string keyName] { get { return ConfigurationManagerItems[keyName]; } set { ConfigurationManagerItems[keyName] = value; } } private static Dictionary ConfigurationManagerItems = new Dictionary(); } 

Esto le permite omitir el acceso completo a un miembro de la clase y simplemente crear una instancia e indexarlo.

  new ConfigurationManager()["ItemName"]