문제

왜 static 인덱에서 허용하지 않는 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;
}

이전 코드를 업그레이드하고 애플리케이션 설정 액세스를 통합 할 수있는 자리를 찾을 수 있다는 이점이 추가됩니다.

또한 필요에(물론,같은 더 좋은)의 정적 인덱을 저장소 특성,그래서 나는 생각이 다소 어색한 해결 방법:

클래스 내에서 당신이 원하는 정적 indexer(여기:소),서브 클래스를 이용해서 만들어진 이름이 같은+"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;
        }
    }
}

그리고 당신은 그것을 사용할 수 있는 하나 대소문자로 입력되지는 않으로 사전

var cnt = element["counter"] as int;
element["counter"] = cnt;

하지만 슬프게도,만약 하나를 실제로 객체 사용으로"value"-입력한 다음,아래 것 여전히 짧(적어도 선언),제공하고 또한 즉각적인 형변환:

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);

이 키워드는 클래스의 현재 인스턴스를 나타냅니다. 정적 멤버 기능에는이 포인터가 없습니다. 이 키워드는 생성자, 인스턴스 메소드 및 인스턴스 액세서의 멤버에 액세스하는 데 사용될 수 있습니다 ( MSDN). 이것은 클래스의 인스턴스를 참조하기 때문에 정적은 클래스의 인스턴스와 관련이 없기 때문에 정적의 특성과 충돌합니다.

하나의 해결 방법은 다음과 같은 경우 개인 사전에 대한 인덱서를 사용할 수 있으므로 새 인스턴스 만 생성하면 정적 부품에 액세스 할 수 있습니다.

    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]

어떤 식 으로든 코드를 더 좋게 만들지는 않습니다. 많은 코드 라인에 의해 작지 않으며 AutoComplete 덕분에 글을 쓰는 것이 쉽지 않으며 '속성'이라고 부르는 것을 얻고 설정하고 있다는 사실을 숨기고 실제로 독자가 강제로 강요하기 때문에 명확하지 않습니다. 인덱서가 정확히 반환하거나 세트하는 내용에 대한 문서를 읽으십시오. 왜냐하면 두 가지 모두와 함께 색인이있는 속성이라는 것이 분명하지 않기 때문입니다.

ConfigurationManager.editProperty(name, value);
...
value = ConfigurationManager.getProperty(name)

당신은 그것을 크게 읽고 코드가 무엇을하는지 즉시 이해할 수 있습니다.

쓰기가 빠른 코드가 아니라 이해하기 쉬운 코드를 작성하고 싶다는 것을 기억하십시오. 프로젝트를 완료하는 속도로 코드를 배치 할 수있는 속도를 착각하지 마십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top