Por que os indexadores estáticos não são permitidos em C #? Não vejo razão para que eles não sejam permitidos e, além disso, podem ser muito úteis.
Por exemplo:
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];
}
}
O código acima se beneficiaria muito com um indexador estático. No entanto, ele não será compilado porque indexadores estáticos não são permitidos. Porque isto é assim?
foreach (var enum in Enum)
:)Respostas:
A notação do indexador requer uma referência a
this
. Como os métodos estáticos não têm uma referência a nenhuma instância específica da classe, você não pode usáthis
-los e, consequentemente, não pode usar a notação do indexador em métodos estáticos.A solução para o seu problema está usando um padrão singleton da seguinte maneira:
Agora você pode ligar
Utilities.ConfigurationManager["someKey"]
usando a notação do indexador.fonte
this
em um indexador não é necessariamente necessário, provavelmente foi escolhido acima de outras palavras-chave porque fazia mais sentido. Para uma implementação estática, a seguinte sintaxe pode ser bastante viável:public object static[string value]
. Não é necessário usar a palavra-chavethis
em um contexto estático.Eu acredito que foi considerado não muito útil. Eu acho que é uma pena também - um exemplo que costumo usar é a codificação, onde
Encoding.GetEncoding("foo")
poderia estarEncoding["Foo"]
. Eu não acho que surgiria com muita frequência, mas, além de qualquer outra coisa, parece um pouco inconsistente não estar disponível.Eu precisaria verificar, mas suspeito que já esteja disponível no IL (idioma intermediário).
fonte
instance
parastatic
IL para uma propriedade e método getter em uma propriedade padrão resulta em reclamação de ilasmosyntax error at token 'static'
; Eu não sou bom em me intrometer nos assuntos de IL, mas isso parece pelo menos um não inicial.Como solução alternativa, você pode definir um indexador de instância em um objeto singleton / estático (diga que o ConfigurationManager é um singleton, em vez de ser uma classe estática):
fonte
Eu também estava precisando (bem, mais parecido com bom) de um indexador estático para armazenar atributos, então descobri uma solução alternativa um tanto estranha:
Dentro da classe que você deseja ter um indexador estático (aqui: Element), crie uma subclasse com o mesmo nome + "Dict". Dê uma estática somente leitura como instância da referida subclasse e adicione o indexador desejado.
Por fim, adicione a classe como importação estática (daí a subclasse para expor apenas o campo estático).
e, em seguida, você pode usá-lo em maiúscula como Tipo ou sem como dicionário:
Mas, infelizmente, se alguém realmente usar o objeto como "value" -Type, o abaixo será ainda mais curto (pelo menos como declaração) e também fornecerá o Typecasting imediato:
fonte
Com as construções mais recentes em C # 6, você pode simplificar o padrão singleton com um corpo de expressão de propriedade. Por exemplo, usei o seguinte atalho que funciona muito bem com a lente de código:
Ele tem o benefício adicional de poder ser encontrado e substituível para atualizar códigos mais antigos e unificar o acesso às configurações do aplicativo.
fonte
A palavra-chave this refere-se à instância atual da classe. As funções de membro estático não possuem um ponteiro this. A palavra-chave this pode ser usada para acessar membros de construtores, métodos de instância e acessadores de instância. (Recuperados de msdn ). Como isso faz referência a uma instância da classe, ela entra em conflito com a natureza da estática, pois estática não está associada a uma instância da classe.
Uma solução alternativa seria a seguinte, que permite que você use o indexador em um Dicionário particular, portanto, você só precisa criar uma nova instância e acessar a parte estática.
Isso permite que você pule todo o acesso a um membro da classe e apenas crie uma instância e o indexe.
fonte
new ()
poderiam ter sido usados para o nome qualificador de um singleton em vez disso, como.Current
this
palavra - chave" e, segundo,this
na sintaxe,public string this[int index]
estritamente falando, nem mesmo o uso de umthis
ponteiro (como pode ocorrer no corpo dos métodos de instância) , mas apenas outro uso do tokenthis
. A sintaxepublic static string this[int index]
pode parecer um pouco contra-intuitiva, mas ainda assim seria inequívoca.public static string class[int index]
.O motivo é que é muito difícil entender exatamente o que você está indexando com um indexador estático.
Você diz que o código se beneficiaria de um indexador estático, mas seria mesmo? Tudo o que faria é mudar isso:
Nisso:
que não melhora o código de forma alguma; não é menor por muitas linhas de código, não é mais fácil escrever graças ao preenchimento automático e é menos claro, pois esconde o fato de que você está recebendo e definindo algo que chama de 'Propriedade' e na verdade força o leitor a vá ler a documentação sobre o que exatamente o indexador retorna ou define, porque não é de forma alguma óbvio que é uma propriedade para a qual você está indexando, enquanto com os dois:
Você pode ler em voz alta e entender imediatamente o que o código faz.
Lembre-se de que queremos escrever um código que seja fácil (= rápido) de entender, não um código que seja rápido de escrever. Não confunda a velocidade com a qual você pode especificar o código com a velocidade com a qual você conclui os projetos.
fonte