none
ArrayListのコンストラクタについての問題です。 RRS feed

  • 質問

  • 今、「ファイルを開く」ダイアログボックス設定のPGを組み込んでいます。
    下記はArrayListについての一部のコードです。

     

    コード ブロック

    ArrayList ArrayList1 = new ArrayList();

                FilterInfo filterInfo  = new FilterInfo();
                FilterInfo filterInfo1  = new FilterInfo();
                FilterInfo filterInfo2  = new FilterInfo();

     

                filterInfo.Name = "XMLファイル(*.xml)";   
                filterInfo.Extension = ".xml";  
                filterInfo1.Name = "テキスト文書(*.txt)";
                filterInfo1.Extension = ".txt";
                filterInfo2.Name = "画像ファイル(*.jpg)";
                filterInfo2.Extension = ".jpg";              
                
                ArrayList1.Add(filterInfo);
                ArrayList1.Add(filterInfo1);
                ArrayList1.Add(filterInfo2);

     

     

     

    *FilterInfo*では、 フィルタインフォ というクラスです。
    *Name(get,set)*   ファイル種類名
    *Extension(get,set)*   ファイル拡張子名

     

    上記コードは、ArrayListクラスのオーバーライド(コピーコンストラクタ)
    を利用すれば、たぶん短くになると思いますが、やりかたはわからないです。

    どうしたら実現できるのか、

    教えて頂けないでしょうか。

    よろしくお願い致します。

    2007年12月12日 2:42

回答

  • やりたいことは「AddとFilterInfoの作成・設定を一行にしたい」でしょうか?

    コード ブロック

        public static class FilterInfoCreator
        {
            public static FilterInfo Create(string name, string extension)
            {
                FilterInfo info = new FilterInfo();
                info.Name = name;
                info.Extension = extension;

                return info;
            }
        }

        class Test
        {
            public static void TestMain()
            {
                List<FilterInfo> list = new List<FilterInfo>();
                list.Add(FilterInfoCreator.Create("XMLファイル(*.xml)", ".xml"));
                list.Add(FilterInfoCreator.Create("テキスト文書(*.txt)", ".txt"));
                list.Add(FilterInfoCreator.Create("画像ファイル(*.jpg)", ".jpg"));
            }
        }

     

     

    ArrayListの方じゃなくて、FilterInfoを一行で作れるようにするとかも1つの方法かと思います。

     

    2007年12月12日 14:42
    モデレータ
  •  剣道 さんからの引用

    arrList内部でFilterInfoのインスタンスを複製して管理することというのは、
    "new DialogUtil.FilterInfo()"は
    Addメソッドの引数として、FilterInfoのインスタンスを作成することなんでしょうか。

     

    ArrayListのAddメソッドの引数に渡すのは、あるインスタンスへの参照です。
    例えば、以下のようにするとどうなるでしょうか?

     

    FilterInfo filterInfo  = new FilterInfo();

     

    filterInfo.Name = "XMLファイル(*.xml)";
    filterInfo.Extension = ".xml";
    ArrayList1.Add(filterInfo);

     

    filterInfo.Name = "テキスト文書(*.txt)";
    filterInfo.Extension = ".txt";
    ArrayList1.Add(filterInfo);

     

    filterInfo.Name = "画像ファイル(*.jpg)";
    filterInfo.Extension = ".jpg";
    ArrayList1.Add(filterInfo);

     

    ArrayList1の中身は全く同じ3つのものになります。ArrayListは実態(インスタンス)がどこにあるかという番地(参照)を保持しているにすぎませんので、3つとも同じ参照を保持していることになり、その参照先には最後にセットされた"画像ファイル(*.jpg)"と".jpg"があります。

     

    上記のコードではnewしているのは最初の1行だけです。例えるならば、ここでマンションの部屋を作って、部屋の番号をfilterInfoにセットしています。
    部屋は1つしか作っていないことに注意して下さい。
    上記で作成された部屋の番号を203号室としましょう。
    ArrayList1には、203号室という情報が3つ入っていることになります。

     

    話を変えます。

     

    FilterInfo filterInfo  = new FilterInfo();

    filterInfo.Name = "XMLファイル(*.xml)";
    filterInfo.Extension = ".xml";
    ArrayList1.Add(filterInfo);

     

    上記コードのArrayList1には203号室という情報のみ入っています。また、ArrayList1は203号室に誰が入るかを管理することができませんので、ArrayList1が知らない間に203号室の住居人(NameとExtension)が変わっている可能性もあります。
    剣道さんの記述にコピーコンストラクタという言葉があったので、ArrayList1が知らない間に住居人が変わると困るというように私は想像しました。


    つまり、

     

    Class ArrayListWrapper
    {
        ArrayList _arrayList = new ArrayList();

     

      public void Add(FilterInfo filterinfo)
        {
           FilterInfo fi = new FilterInfo();    //新しい部屋を作る。503号室ができたとする。

           fi.Name = filterinfo.Name;
           fi.Extension = filterinfo.Extension;

           _arrayList.Add(fi);
        }
    }

    のようにして新しい部屋を作って、そこに住居人をコピーして住まわせることかと思ったのです。(クローン人間ですね(^^;)


    203号室と503号室には全く同じ住居人(NameとExtension)がいることになります。(503号室にいるのはクローン人間です。)
    このため、このあと203号室とその住居人がどうなろうが、ArrayListWrapper内にある503号室とその住居人には全く影響がないわけです。


    私が、

    「考えてみれば、Addメソッドの引数でnewされているため、newされたインスタンスをarrList以外で参照していませんから、arrList内部でFilterInfoのインスタンスを複製して管理することと実質は同じようなことになりますね。」

    と書いたのは、203号室という情報はarrList以外にはわからないので、他から203号室をいじられる心配がないため、503号室というコピーを作らなくても同じようなことだと思ったからです。つまり、ArrayList内でFilterInfoのインスタンスを作っているのと実質的には変わらないわけです。

    2007年12月13日 5:43
    モデレータ

すべての返信

  • コピーコンストラクタというよりは、ArrayListへAddするのはインスタンスへの参照ではなく、ArrayList内部にインスタンス自体を複製して持ちたいということなんでしょうか?

    2007年12月12日 3:09
    モデレータ
  • trapemiyaさんへ

    ご返事をいただき、ありがとうございます。

    はい、仰られたように、単純にArrayList1にオブジェクトを追加するのではないです。

    ArrayList内部にインスタンス自体を複製して持ちたいです。

     

     

     

     

    2007年12月12日 3:26
  • ArrayList自体はObject型、つまり参照を扱うようにできているため、ArrayListをどうこうするよりも、ArrayListを内部にラップしたクラスを作成してしまえば良いでしょう。つまり、そのクラスでAddメソッドを定義し、Addメソッドに渡された引数からインスタンスのコピーを作成し(この場合、ディープコピーです)、これを内部のArrayListで管理するようにしてしまえば良いはずです。

     

    #ArrayListではなくて、C#2.0以降ならListを使うべきです。

    2007年12月12日 6:05
    モデレータ
  • やりたいことは「AddとFilterInfoの作成・設定を一行にしたい」でしょうか?

    コード ブロック

        public static class FilterInfoCreator
        {
            public static FilterInfo Create(string name, string extension)
            {
                FilterInfo info = new FilterInfo();
                info.Name = name;
                info.Extension = extension;

                return info;
            }
        }

        class Test
        {
            public static void TestMain()
            {
                List<FilterInfo> list = new List<FilterInfo>();
                list.Add(FilterInfoCreator.Create("XMLファイル(*.xml)", ".xml"));
                list.Add(FilterInfoCreator.Create("テキスト文書(*.txt)", ".txt"));
                list.Add(FilterInfoCreator.Create("画像ファイル(*.jpg)", ".jpg"));
            }
        }

     

     

    ArrayListの方じゃなくて、FilterInfoを一行で作れるようにするとかも1つの方法かと思います。

     

    2007年12月12日 14:42
    モデレータ
  • trapemiyaさん Azuleanさんへ
    返事が遅くなって、すみませんでした。


    私が勉強不足のため、ArrayListを採用の意味はまた理解していないです。
    trapemiyaさんから教えて頂いた知識をメモにして、将来活用していきたいと思っています。

     

    Azuleanさんから教えて頂いた方法を参照し、
    FilterInfoクラスで、ふたつ引数のコンストラクタを追加して、解決しました。


    public class FilterInfo
            {
                public string _name;            // ファイル名
                public string[] _extensions;      // ファイル拡張子名

                public FilterInfo(string fileName, string[] fileExtensions)
                {
                    _name = fileName;
                    _extensions = fileExtensions;
                }

     

    *************************************
                ArrayList arrList = new ArrayList();
                string[] Extensions = { "jpg", "jpeg", "jpe", "jfif","bmp","gif" };

                // 2つの引数を指定したFilterInfoインスタンスを作成して、ArrayListに追加する。
                arrList.Add(new DialogUtil.FilterInfo("XMLファイル(*.xml)", "xml"));
                arrList.Add(new DialogUtil.FilterInfo("テキスト文書(*.txt)", "txt"));
                arrList.Add(new DialogUtil.FilterInfo("画像ファイル(*.JPG;*.JPEG;*.JPE;*.JFIF;*.BMP;*.GIF)", Extensions));

     

    迅速にご丁寧に回答していただきまして、心から感謝しています。
    非常に勉強になりました。
    また、よろしくお願いたします。

    2007年12月13日 0:41
  •  剣道 さんからの引用

    私が勉強不足のため、ArrayListを採用の意味はまた理解していないです。

     

    以下が参考になると思います。

     

    ジェネリックとは何か?
    http://www.atmarkit.co.jp/fdotnet/csharp20/csharp20_02/csharp20_02_01.html

     

     剣道 さんからの引用

    Azuleanさんから教えて頂いた方法を参照し、
    FilterInfoクラスで、ふたつ引数のコンストラクタを追加して、解決しました。

     

    考えてみれば、Addメソッドの引数でnewされているため、newされたインスタンスをarrList以外で参照していませんから、arrList内部でFilterInfoのインスタンスを複製して管理することと実質は同じようなことになりますね。

    2007年12月13日 1:13
    モデレータ
  • trapemiyaさんへ
    たくさんのことを教えて頂き、ありがとうございます。


    実は、私の目的が、FilterInfoという適当なクラスつくり、複数のインスタンスをarrList に格納して、
    foreach 文で、格納した各要素をアクセスしたかったです。

    今、作ったFilterInfoのインスタンスは、確か他の参照していないです。

    恥ずかしいですが、現時点で、単純なことしか分からないです。
    クラス内部ということは、ちょっと難しい話だと思います。

     

    arrList内部でFilterInfoのインスタンスを複製して管理することというのは、
    "new DialogUtil.FilterInfo()"は
    Addメソッドの引数として、FilterInfoのインスタンスを作成することなんでしょうか。

     

    申し訳ありませんが、よろしければ、簡単に説明して頂けないでしょうか。

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

     

    2007年12月13日 2:35
  •  剣道 さんからの引用

    arrList内部でFilterInfoのインスタンスを複製して管理することというのは、
    "new DialogUtil.FilterInfo()"は
    Addメソッドの引数として、FilterInfoのインスタンスを作成することなんでしょうか。

     

    ArrayListのAddメソッドの引数に渡すのは、あるインスタンスへの参照です。
    例えば、以下のようにするとどうなるでしょうか?

     

    FilterInfo filterInfo  = new FilterInfo();

     

    filterInfo.Name = "XMLファイル(*.xml)";
    filterInfo.Extension = ".xml";
    ArrayList1.Add(filterInfo);

     

    filterInfo.Name = "テキスト文書(*.txt)";
    filterInfo.Extension = ".txt";
    ArrayList1.Add(filterInfo);

     

    filterInfo.Name = "画像ファイル(*.jpg)";
    filterInfo.Extension = ".jpg";
    ArrayList1.Add(filterInfo);

     

    ArrayList1の中身は全く同じ3つのものになります。ArrayListは実態(インスタンス)がどこにあるかという番地(参照)を保持しているにすぎませんので、3つとも同じ参照を保持していることになり、その参照先には最後にセットされた"画像ファイル(*.jpg)"と".jpg"があります。

     

    上記のコードではnewしているのは最初の1行だけです。例えるならば、ここでマンションの部屋を作って、部屋の番号をfilterInfoにセットしています。
    部屋は1つしか作っていないことに注意して下さい。
    上記で作成された部屋の番号を203号室としましょう。
    ArrayList1には、203号室という情報が3つ入っていることになります。

     

    話を変えます。

     

    FilterInfo filterInfo  = new FilterInfo();

    filterInfo.Name = "XMLファイル(*.xml)";
    filterInfo.Extension = ".xml";
    ArrayList1.Add(filterInfo);

     

    上記コードのArrayList1には203号室という情報のみ入っています。また、ArrayList1は203号室に誰が入るかを管理することができませんので、ArrayList1が知らない間に203号室の住居人(NameとExtension)が変わっている可能性もあります。
    剣道さんの記述にコピーコンストラクタという言葉があったので、ArrayList1が知らない間に住居人が変わると困るというように私は想像しました。


    つまり、

     

    Class ArrayListWrapper
    {
        ArrayList _arrayList = new ArrayList();

     

      public void Add(FilterInfo filterinfo)
        {
           FilterInfo fi = new FilterInfo();    //新しい部屋を作る。503号室ができたとする。

           fi.Name = filterinfo.Name;
           fi.Extension = filterinfo.Extension;

           _arrayList.Add(fi);
        }
    }

    のようにして新しい部屋を作って、そこに住居人をコピーして住まわせることかと思ったのです。(クローン人間ですね(^^;)


    203号室と503号室には全く同じ住居人(NameとExtension)がいることになります。(503号室にいるのはクローン人間です。)
    このため、このあと203号室とその住居人がどうなろうが、ArrayListWrapper内にある503号室とその住居人には全く影響がないわけです。


    私が、

    「考えてみれば、Addメソッドの引数でnewされているため、newされたインスタンスをarrList以外で参照していませんから、arrList内部でFilterInfoのインスタンスを複製して管理することと実質は同じようなことになりますね。」

    と書いたのは、203号室という情報はarrList以外にはわからないので、他から203号室をいじられる心配がないため、503号室というコピーを作らなくても同じようなことだと思ったからです。つまり、ArrayList内でFilterInfoのインスタンスを作っているのと実質的には変わらないわけです。

    2007年12月13日 5:43
    モデレータ
  • trapemiyaさんへ

    多くの質問にご丁寧にお答え頂き、簡単な例から説明して頂き、本当にありがとうございます!


    ご返信を読みましたら、ArrayListクラスについて、大体は理解できたと思います。

    やはりクラスやメソッドの機能を明確しなくてはいけないですね。
    たぶんかなり時間かかると思います・・・

    試して、研究していきたいと思います。

     

    お忙しいところお手間とらせてすみませんでした。
    また、よろしくお願いいたします。

     

    2007年12月13日 8:21