none
C#でのString型の参照を持つ方法について RRS feed

  • 質問

  • お世話になっております。

    今回、インデクサーを使用してString型の変数とKeyValuePairのやり取りを考えております。
    しかし、普通のクラスとString型の参照の持たせ方が違うようで以下のやりたいことができません。
    何か方法がおありでしたらご教授いただければと存じます。

    やりたいこと

        class ClassA {
            private Dictionary<string, string> dict = new Dictionary<string, string>();
            public ClassA() {
                dict.Add("key1", property1);
                dict.Add("key2", property2);
            }
            public string this[string key] {
                get { return dict[key]; } // こっちは使わない
                set { dict[key] = value; }
            }
            public string property1 { get; set; } // classA.property1でもアクセスする
            public string property2 { get; set; }
        }

    このようなクラスに対して

                var classA = new ClassA();
                foreach (var kvp in GetValues()) { // 他からKeyValuePair<string, string>を取得する
                    classA[kvp.Key] = kvp.Value;
                }

    このような処理で値を格納したいのです。
    現状泥臭いコードで何とかしている状態ですが、
    後々サンプルとして配る際に困ります。

                public string this[string key]{
                    get {
                        string result;
                        switch (key)
                        {
                            case "key1":
                                result = property1;
                                break;
                            case "key2":
                                result = property2;
                                break;
                            default:
                                result = null;
                                break;
                        }
                        return result;
                    }
                    set {
                        switch (key)
                        {
                            case "key1":
                                property1 = value;
                                break;
                            case "key2":
                                property2 = value;
                                break;
                            default:
                                break;
                        }
                    }
                }

    以上よろしくお願いいたします。

    以上よろしくお願いいたします。
    以上よろしくお願いいたします。
    2019年10月16日 6:35

回答

  • これでいいような気がします。

        class ClassA
        {
            private Dictionary<string, string> dict = new Dictionary<string, string>();
    
            public ClassA() {
                property1 = null;
                property2 = null;
            }
    
            public string this[string key] {
                get { return dict[key]; }
                set { dict[key] = value; }
            }
    
            public string property1 {
                get { return this["key1"]; }
                set { this["key1"] = value; }
            }
    
            public string property2 {
                get { return this["key2"]; }
                set { this["key2"] = value; }
            }
        }
    

    2019年10月16日 8:10
  • Stringでなければどう実装できるのか気になりますが…。

    基本的にはデータは全部dictに挿入して、property1等はdictから取得・dictに設定する形になるかと思います。

    public string property1
    {
        get { this.dict["key1"]; }
        set { this.dict["key1"] = value; }
    }

    (property1と"key1"という文字列がどう関連付けられるのか分からないのでとりあえず直値で書いています)

    getの方は、dictに"key1"が存在しない場合どうするかという判断が恐らく必要になるでしょう。

    this[string key]の方は単純にdictに対して取得設定すればよく、property1やらを意識する必要はないはずです。

    2019年10月16日 8:11

すべての返信

  • これでいいような気がします。

        class ClassA
        {
            private Dictionary<string, string> dict = new Dictionary<string, string>();
    
            public ClassA() {
                property1 = null;
                property2 = null;
            }
    
            public string this[string key] {
                get { return dict[key]; }
                set { dict[key] = value; }
            }
    
            public string property1 {
                get { return this["key1"]; }
                set { this["key1"] = value; }
            }
    
            public string property2 {
                get { return this["key2"]; }
                set { this["key2"] = value; }
            }
        }
    

    2019年10月16日 8:10
  • Stringでなければどう実装できるのか気になりますが…。

    基本的にはデータは全部dictに挿入して、property1等はdictから取得・dictに設定する形になるかと思います。

    public string property1
    {
        get { this.dict["key1"]; }
        set { this.dict["key1"] = value; }
    }

    (property1と"key1"という文字列がどう関連付けられるのか分からないのでとりあえず直値で書いています)

    getの方は、dictに"key1"が存在しない場合どうするかという判断が恐らく必要になるでしょう。

    this[string key]の方は単純にdictに対して取得設定すればよく、property1やらを意識する必要はないはずです。

    2019年10月16日 8:11
  • お二方のやり方で確かにできますね。
    私の想像力不足でした。
    ありがとうございました。

    通常のクラスならというのは以下の書き方での話でした。
    普段私が使っているやり方がClassBのものですが、
    設定xmlなどを他人がわかりやすくするために連番の番号を付けたオブジェクトを

    <Hoge1>
        <Hogehoge>hogehoge</Hogehoge>
    </Hoge1>
    <Hoge2>
        <Hogehoge>hogehoge</Hogehoge>
    </Hoge2>
    <Hoge3>
        <Hogehoge>hogehoge</Hogehoge>
    </Hoge3>
    のような形で割り振ってプログラムの中で配列に落とし込むような処理をしているのですが、

    それをString型でやろうとするとできなくなったので困っていました。

    下を実行するとわかるのですが、ClassBではDictionaryに参照を渡してそのDictionaryで連続処理をさせられるのですが、
    String型だと新しい参照を渡すことになるのでClassAでは同じやり方ではできないんですよね。

    class Program {
            static void Main(string[] args) {
                var classA = new ClassA();
                classA["key1"] = "Hogehoge";
                Console.WriteLine(classA.property1); // null
                var classB = new ClassB();
                classB["key1"].Hogehoge = "Hogehoge";
                Console.WriteLine(classB.property1.Hogehoge); // Hogehoge
            }
        }
        class Hoge {
            public string Hogehoge { get; set; }
        }
        class ClassB {
            private Dictionary<string, Hoge> dict = new Dictionary<string, Hoge>();
            public ClassB() {
                property1 = new Hoge();
                property2 = new Hoge();
                dict.Add("key1", property1);
                dict.Add("key2", property2);
            }
            public Hoge this[string key]{
                get { return dict[key]; }
                set { dict[key] = value; }
            }
            public Hoge property1 { get; set; }
            public Hoge property2 { get; set; }
        }

    2019年10月16日 8:40