132

静的インデクサーが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];
        }
    }

上記のコードは、静的インデクサーから大きな恩恵を受けます。ただし、静的インデクサーは許可されていないため、コンパイルされません。なんでそうなの?

4

7 に答える 7

99

あまり役に立たないと考えられていたと思います。Encoding.GetEncoding("foo")私もそれは残念だと思います - 私がよく使う例は EncodingEncoding["Foo"]です。あまり頻繁に出てくるとは思いませんが、他のことを除けば、利用できないのは少し矛盾しているように感じます.

確認する必要がありますが、すでに IL (Intermediate Language) で利用できると思われます。

于 2008-12-30T20:20:59.617 に答える
76

インデクサー表記には、への参照が必要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"]これで、インデクサー表記を使用して呼び出すことができます。

于 2008-12-30T19:47:48.653 に答える
9

回避策として、シングルトン/静的オブジェクトにインスタンスインデクサーを定義できます(ConfigurationManagerは静的クラスではなく、シングルトンであると言います)。

class ConfigurationManager
{
  //private constructor
  ConfigurationManager() {}
  //singleton instance
  public static ConfigurationManager singleton;
  //indexer
  object this[string name] { ... etc ... }
}
于 2008-12-30T19:42:16.933 に答える
1

また、属性を格納するための静的インデクサーが必要だったので (あると便利なように)、やや厄介な回避策を見つけました。

静的インデクサー (ここでは要素) を作成するクラス内で、同じ名前 + "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;

しかし残念なことに、実際にオブジェクトを「値」型として使用する場合、以下はさらに短くなり (少なくとも宣言として)、即時の型キャストも提供します。

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);
于 2019-03-05T15:12:47.967 に答える
-2

this キーワードは、クラスの現在のインスタンスを参照します。静的メンバー関数には this ポインターがありません。this キーワードを使用して、コンストラクター、インスタンス メソッド、およびインスタンス アクセサー内からメンバーにアクセスできます ( msdnから取得)。これはクラスのインスタンスを参照するため、静的はクラスのインスタンスに関連付けられていないため、静的の性質と競合します。

1 つの回避策は次のとおりです。これにより、プライベート ディクショナリに対してインデクサーを使用できるため、新しいインスタンスを作成するだけで静的部分にアクセスできます。

    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"]
于 2013-10-27T07:22:58.483 に答える