정적 인덱서?
C #에서 정적 인덱서가 허용되지 않는 이유는 무엇입니까? 나는 그들이 왜 허용되지 않는 유용하는지 전혀 알지 못하며 더욱 할 수 있습니다.
예를 들면 다음과 같습니다.
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];
}
}
위의 코드는 정적 인덱서에서 큰 이점을 얻을 수 있습니다. 그러나 정적 인덱서가 허용되지 않습니다. 왜 그렇습니까?
인덱서 표기법에 대한 참조가 필요합니다 this
. 정적 메서드에는 클래스의 특정 인스턴스에 대한 참조가 없습니다. this
와 함께 사용할 수있는 정적 메서드에 인덱서 표기법을 사용할 수 없습니다.
하나에 대한 해결책은 다음과 같이 단일 문제 패턴을 사용하는 것입니다.
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
}
}
이제 Utilities.ConfigurationManager["someKey"]
인덱서 표기법을 사용하여 호출 할 수 있습니다 .
나는 그것이별로 유용하지 않다고 생각되었다고 생각합니다. 내가 너무 수치를 생각 - 내가 사용하는 경향이 예는 인코딩입니다 Encoding.GetEncoding("foo")
될 수있다 Encoding["Foo"]
. 나는 그것이 올 것이라고 생각하지 않는다 매우 자주하지만, 따로 다른 어떤에서 그것은 단지 약간의 일관성 사용할 수 없습니다 느낀다.
확인해야하지만 이미 IL (중간 언어)에서 사용할 수 있다고 생각 합니다.
해결 방법으로 싱글 톤 / 정적 객체에 인스턴스 인덱서를 정의 할 수 있습니다 (예 : ConfigurationManager가 정적 클래스가 아닌 싱글 톤이라고 가정).
class ConfigurationManager
{
//private constructor
ConfigurationManager() {}
//singleton instance
public static ConfigurationManager singleton;
//indexer
object this[string name] { ... etc ... }
}
C # 6의 최신 구문을 사용하면 속성 식 본문으로 싱글 톤 패턴을 단순화 할 수 있습니다. 예를 들어, 코드 렌스와 잘 작동하는 다음 단축키를 사용했습니다.
public static class Config
{
public static NameValueCollection Get => ConfigurationManager.AppSettings;
}
이전 코드를 업그레이드하고 애플리케이션 설정 액세스를 통합하기 위해 찾기-교체가 가능하다는 추가 이점이 있습니다.
또한 속성을 저장하기 위해 정적 인덱서가 필요했기 때문에 다소 어색한 해결 방법을 찾았습니다.
정적 인덱서 (여기서는 요소)를 원하는 클래스 내에서 동일한 이름 + "Dict"의 하위 클래스를 만듭니다. 해당 하위 클래스의 인스턴스로 읽기 전용 정적을 지정한 다음 원하는 인덱서를 추가하십시오.
마지막으로 클래스를 정적 가져 오기로 추가합니다 (따라서 하위 클래스는 정적 필드 만 노출 함).
import static Element.ElementDict;
public class Element {
// ....
private static readonly Dictionary<string, object> elemDict = new Dictionary<string, object>();
public class ElementDict {
public readonly static ElementDict element = new ElementDict();
public object this[string key] {
get => elemDict.TryGetValue(key, out object o) ? o : null;
set => elemDict[key] = value;
}
}
}
그런 다음 Type으로 대문자로 사용하거나 사전으로 사용하지 않고 사용할 수 있습니다.
var cnt = element["counter"] as int;
element["counter"] = cnt;
그러나 아아, 실제로 "value"-Type으로 객체를 사용한다면, 아래는 여전히 더 짧을 것입니다 (적어도 선언으로). 또한 즉각적인 Typecasting을 제공합니다.
public static T load<T>(string key) => elemDict.TryGetValue(key, out object o) ? (T) o : default(T);
public static void store<T>(string key, T value) => elemDict[key] = value;
var cnt = Element.load<int>("counter");
Element.store("counter", cnt);
this 키워드는 클래스의 현재 인스턴스를 나타냅니다. 정적 멤버 함수에는 this 포인터가 없습니다. this 키워드는 생성자, 인스턴스 메서드 및 인스턴스 접근 자 내에서 멤버에 액세스하는 데 사용할 수 있습니다 ( msdn 에서 검색 됨 ). 이것은 클래스의 인스턴스를 참조하기 때문에 static은 클래스의 인스턴스와 연관되지 않기 때문에 static의 특성과 충돌합니다.
한 가지 해결 방법은 다음과 같이 개인 사전에 대해 인덱서를 사용할 수 있으므로 새 인스턴스를 만들고 정적 부분에 액세스하기 만하면됩니다.
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>();
}
이를 통해 클래스 멤버에 액세스하는 전체를 건너 뛰고 인스턴스를 생성하고 인덱스 할 수 있습니다.
new ConfigurationManager()["ItemName"]
그 이유는 정적 인덱서로 정확히 무엇을 인덱싱하고 있는지 이해하기가 매우 어렵 기 때문입니다.
코드가 정적 인덱서의 이점을 얻을 수 있다고 말했지만 실제로는 그럴까요? 이것이 할 일은 이것을 변경하는 것입니다.
ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)
이것으로 :
ConfigurationManager[name] = value
...
value = ConfigurationManager[name]
어떤 식 으로든 코드를 더 좋게 만들지는 않습니다. 여러 줄의 코드로 작지 않으며 자동 완성 기능 덕분에 작성하기가 쉽지 않으며 '속성'이라고 부르는 것을 얻고 설정한다는 사실을 숨기고 실제로 독자가 인덱서가 정확히 무엇을 반환하거나 설정하는지에 대한 문서를 읽으십시오. 두 가지 모두를 사용하는 동안 인덱싱하는 속성이 분명하지 않기 때문입니다.
ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)
큰 소리로 읽고 코드가하는 일을 즉시 이해할 수 있습니다.
빠른 코드가 아니라 이해하기 쉬운 (= 빠른) 코드를 작성하고 싶다는 것을 기억하십시오. 프로젝트를 완료하는 속도와 코드를 놓을 수있는 속도를 착각하지 마십시오.
참고 URL : https://stackoverflow.com/questions/401232/static-indexers
'IT' 카테고리의 다른 글
공유 라이브러리에서 동적으로 링크 될 때 전역 및 정적 변수는 어떻게? (0) | 2020.07.27 |
---|---|
Entity Framework Code First는 저장 프로 시저를 지원합니까? (0) | 2020.07.27 |
Linux에서 여러 가지로 신호 처리 (0) | 2020.07.27 |
프로토콜이 자체 준수하지 않습니까? (0) | 2020.07.27 |
C ++, 프리 스토어 및 힙 (0) | 2020.07.27 |