remarks generate example c# .net static indexer static-indexers

generate - params comments c#



Indicadores estáticos? (5)

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

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]; } }

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


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 ... } }


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.


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 { 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 } } }

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


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 msdn 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<string, object> ConfigurationManagerItems = new Dictionary<string, object>(); }

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

new ConfigurationManager()["ItemName"]


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.