¿Por qué no se permiten los indexadores estáticos en C #? No veo ninguna razón por la que no deban permitirse 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);
}
/// <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];
}
}
El código anterior se beneficiaría enormemente de un indexador estático. Sin embargo, no se compilará porque no se permiten indexadores estáticos. ¿Por qué esto es tan?
foreach (var enum in Enum)
:)Respuestas:
La notación del indexador requiere una referencia a
this
. Dado que los métodos estáticos no tienen una referencia a ninguna instancia particular de la clase, no puede usarlosthis
y, en consecuencia, no puede usar la notación indexadora en métodos estáticos.La solución a su problema es usar un patrón singleton de la siguiente manera:
Ahora puedes llamar
Utilities.ConfigurationManager["someKey"]
usando la notación indexadora.fuente
this
en un indexador no es necesariamente obligatorio, probablemente se eligió por encima de otras palabras clave porque tenía más sentido. Para una implementación estática, la sintaxis siguiente puede ser muy viable:public object static[string value]
. No es necesario utilizar la palabra clavethis
en un contexto estático.Creo que no se consideró muy útil. Creo que también es una pena; un ejemplo que suelo usar es Encoding, donde
Encoding.GetEncoding("foo")
podría estarEncoding["Foo"]
. No creo que surja muy a menudo, pero aparte de cualquier otra cosa, parece un poco inconsistente no estar disponible.Tendría que comprobarlo, pero sospecho que ya está disponible en IL (idioma intermedio).
fuente
instance
astatic
en IL para una propiedad y un método de obtención en una propiedad predeterminada da como resultado que ilasm se quejesyntax error at token 'static'
; No soy muy bueno para entrometerme en los asuntos de IL, pero eso suena al menos como un no inicial.Como solución alternativa, puede definir un indexador de instancias en un objeto singleton / estático (digamos que ConfigurationManager es un singleton, en lugar de ser una clase estática):
fuente
También necesitaba (bueno, más bien tenerlo) de un indexador estático para almacenar atributos, así que descubrí una solución un tanto incómoda:
Dentro de la clase que desea tener un indexador estático (aquí: Elemento), cree una subclase del mismo nombre + "Dict". Déle una instancia estática de solo lectura como instancia de dicha subclase, y luego agregue su indexador deseado.
Por último, agregue la clase como importación estática (de ahí la subclase para exponer solo el campo estático).
y luego puede usarlo en mayúsculas como Tipo o sin como diccionario:
Pero, por desgracia, si uno realmente usara el objeto como "valor" -Tipo, entonces lo siguiente sería aún más corto (al menos como declaración), y también proporcionaría encasillado inmediato:
fuente
Con las construcciones más nuevas de C # 6, puede simplificar el patrón singleton con un cuerpo de expresión de propiedad. Por ejemplo, utilicé el siguiente atajo que funciona muy bien con el código de lente:
Tiene el beneficio adicional de ser reemplazable para actualizar el código anterior y unificar el acceso a la configuración de la aplicación.
fuente
La palabra clave this se refiere a la instancia actual de la clase. Las funciones miembro estáticas no tienen un puntero this. La palabra clave this se puede usar para acceder a miembros desde dentro de constructores, métodos de instancia y accesores de instancia (recuperado de msdn ). Dado que esto hace referencia a una instancia de la clase, entra en conflicto con la naturaleza de static, ya que static no está asociado 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.
Esto le permite omitir todo el acceso a un miembro de la clase y simplemente crear una instancia e indexarlo.
fuente
new ()
podrían haberse utilizado para el nombre de calificador de un singleton en cambio, como.Current
this
palabra clave", y segundo,this
en la sintaxis,public string this[int index]
estrictamente hablando, ni siquiera es un uso de unthis
puntero (como puede ocurrir en el cuerpo de los métodos de instancia) , pero solo otro uso del tokenthis
. La sintaxispublic static string this[int index]
puede parecer un poco contradictoria, pero aún así sería inequívoca.public static string class[int index]
.La razón es porque es bastante difícil entender qué es exactamente lo que está indexando con un indexador estático.
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:
Dentro de esto:
que no mejora el código de ninguna manera; no es más pequeño en muchas líneas de código, no es más fácil de escribir gracias al autocompletar y es menos claro, ya que oculta el hecho de que está obteniendo y configurando algo que llama 'Propiedad' y en realidad obliga al lector a vaya a leer la documentación sobre qué devuelve o establece exactamente el indexador, porque de ninguna manera es obvio que es una propiedad por la que está indexando, mientras que con ambos:
Puede leerlo en voz alta y comprender de inmediato lo que hace el código.
Recuerde que queremos escribir código que sea fácil (= rápido) de entender, no código que sea rápido de escribir. No confunda la velocidad a la que puede establecer el código con la velocidad a la que completa los proyectos.
fuente