Dlaczego statyczne indeksatory są niedozwolone w C #? Nie widzę powodu, dla którego nie miałyby być dozwolone, a ponadto mogłyby być bardzo przydatne.
Na przykład:
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];
}
}
Powyższy kod znacznie skorzystałby na statycznym indeksatorze. Jednak nie zostanie skompilowany, ponieważ indeksatory statyczne są niedozwolone. Dlaczego tak jest?
foreach (var enum in Enum)
:)Odpowiedzi:
Notacja indeksatora wymaga odwołania do
this
. Ponieważ metody statyczne nie mają odniesienia do żadnego konkretnego wystąpienia klasy, nie można ich używaćthis
, a tym samym nie można używać notacji indeksującej w metodach statycznych.Rozwiązaniem tego problemu jest użycie wzorca singleton w następujący sposób:
Teraz możesz wywoływać
Utilities.ConfigurationManager["someKey"]
używając notacji indeksującej.źródło
this
w indeksatorze niekoniecznie jest wymagane, prawdopodobnie zostało wybrane ponad innymi słowami kluczowymi, ponieważ miało największy sens. Dla statycznego realizacji następujące składnia może być bardzo opłacalne:public object static[string value]
. Nie ma potrzeby używania słowa kluczowegothis
w kontekście statycznym.Uważam, że uznano to za niezbyt przydatne. Myślę, że to też wstyd - przykładem, którego zwykle używam, jest kodowanie, gdzie
Encoding.GetEncoding("foo")
mogłoby byćEncoding["Foo"]
. Nie sądzę, by pojawiało się to zbyt często, ale poza wszystkim innym wydaje się to trochę niekonsekwentne, że nie jest dostępny.Musiałbym to sprawdzić, ale podejrzewam, że jest już dostępny w języku IL (język pośredni).
źródło
instance
nastatic
w IL dla właściwości i metody pobierającej dla właściwości domyślnej powoduje narzekanie ilasmsyntax error at token 'static'
; Nie jestem świetny w wtrącaniu się w sprawy IL, ale to brzmi jak przynajmniej początkowe „nie”.Aby obejść ten problem, możesz zdefiniować indeksator instancji na obiekcie pojedynczym / statycznym (powiedzmy, że ConfigurationManager jest singletonem, a nie klasą statyczną):
źródło
Potrzebowałem również (no cóż, raczej przyjemnego do posiadania) statycznego indeksatora do przechowywania atrybutów, więc znalazłem nieco niezręczne obejście:
W klasie, w której chcesz mieć statyczny indeksator (tutaj: Element), utwórz podklasę o tej samej nazwie + „Dict”. Nadaj mu tylko do odczytu static jako wystąpienie wspomnianej podklasy, a następnie dodaj żądany indeksator.
Na koniec dodaj klasę jako import statyczny (stąd podklasa, aby ujawnić tylko pole statyczne).
a następnie możesz użyć go wielkimi literami jako Typ lub bez jako słownika:
Ale niestety, gdybyśmy faktycznie użyli obiektu jako "wartości" -Type, to poniżej byłby jeszcze krótszy (przynajmniej jako deklaracja), a także zapewniłby natychmiastowe rzutowanie:
źródło
Dzięki nowszym konstrukcjom w języku C # 6 można uprościć wzorzec singleton za pomocą treści wyrażenia właściwości. Na przykład użyłem następującego skrótu, który działa dobrze z lense kodu:
Dodatkową zaletą jest możliwość znajdowania i zastępowania w celu uaktualnienia starszego kodu i ujednolicenia dostępu do ustawień aplikacji.
źródło
Słowo kluczowe this odnosi się do bieżącej instancji klasy. Statyczne funkcje składowe nie mają wskaźnika this. Słowa kluczowego this można używać do uzyskiwania dostępu do elementów członkowskich z poziomu konstruktorów, metod instancji i akcesorów instancji (pobieranych z msdn ). Ponieważ odwołuje się do instancji klasy, koliduje z naturą static, ponieważ static nie jest skojarzone z instancją klasy.
Jedynym obejściem byłoby następujące, które umożliwia użycie indeksatora w odniesieniu do prywatnego słownika, więc wystarczy utworzyć nowe wystąpienie i uzyskać dostęp do części statycznej.
Pozwala to pominąć cały proces uzyskiwania dostępu do członka klasy i po prostu utworzyć jego instancję i ją zindeksować.
źródło
new ()
mogłyby zostać użyte do nazwy kwalifikatora singletona zamiast tego, jak.Current
this
słowa kluczowego”, a po drugie,this
w składnipublic string this[int index]
ściśle mówiąc, nie jest to nawet użyciethis
wskaźnika (jak może się to zdarzyć w treści metod instancji) , ale po prostu kolejne użycie tokenathis
. Składniapublic static string this[int index]
może wyglądać nieco sprzecznie z intuicją, ale nadal byłaby jednoznaczna.public static string class[int index]
.Powodem jest to, że dość trudno jest zrozumieć, co dokładnie indeksujesz za pomocą statycznego indeksatora.
Mówisz, że kod skorzystałby na statycznym indeksatorze, ale czy naprawdę? Wszystko, co by zrobił, to zmienić to:
Zaangażowany w to:
co w żaden sposób nie czyni kodu lepszym; nie jest mniejszy o wiele linii kodu, nie jest łatwiejszy do pisania dzięki autouzupełnianiu i jest mniej czytelny, ponieważ ukrywa fakt, że otrzymujesz i ustawiasz coś, co nazywasz `` właściwością '' i faktycznie zmusza czytelnika do przeczytaj dokumentację na temat tego, co dokładnie indeksator zwraca lub ustawia, ponieważ nie jest w żaden sposób oczywiste, że jest to właściwość, dla której indeksujesz, podczas gdy oba:
Możesz przeczytać to na głos i od razu zrozumieć, co robi kod.
Pamiętaj, że chcemy napisać kod, który jest łatwy (= szybki) do zrozumienia, a nie kod, który można szybko napisać. Nie myl szybkości, z jaką można układać kod, z szybkością, z jaką wykonujesz projekty.
źródło