C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

No.63710 の関連記事表示

<< 0 >>
■63710  Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 09:51:13)

    分類:[C#] 

    C#のクラスの設計で悩んでいます。
    複数のクラスで共有するデータがあるのですが、それに対するアクセスはI/F用のクラスを介したものだけに制限したい。
    そこで以下のようなクラスを作りました。

    // データの構造(I/Fとして用意)
    public class Data
    {
    public int a;
    public int b;
    }

    public class DataManager
    {
    // データ(実装を外部に見せたくない)
    private List<Data> _dataList = new List<Data>();

    // データ追加
    public void Add(Data value)
    {
    _dataList.Add(value);
    }
    }

    それで、データを取得するためのI/Fを追加したいのですが、_dataListを外に見せることなく、List<Data>の型でデータを取得する場合、どのようにするのがベターなのでしょうか。
    _dataListの実装は将来変わる可能性があり(例えばSQLiteのようなデータベース)、_dataListそのものを返すことは避けたいのです。
    今、考えているのは、_dataListのCloneを作成して返すくらいです。
    他に良い方法があれば教えてください。
親記事 /過去ログ107より / 関連記事表示
削除チェック/

■63711  Re[1]: Listデータの隠蔽の方法
□投稿者/ shu -(2012/09/30(Sun) 10:26:45)
    No63710 (亜守 さん) に返信

    DataManagerにList<Data>の公開したいメソッドをすべて実装すればよいです。
    List<Data>型として公開したいのであれば提示されたようにしてもよいと思います。
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63712  Re[2]: Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 12:42:20)
    No63711 (shu さん) に返信

    確かに、その通りですね。
    例えば、特定のキーにより要素を検索して返すだとか、N番目の要素を返すだとか、
    そういった類のものは、それで行けそうです。

    呼び元で、foreachを使いたい場合は、List<Data>型として公開する必要があるので、
    その場合は他に方法はないですかね?

    > ■No63710 (亜守 さん) に返信
    >
    > DataManagerにList<Data>の公開したいメソッドをすべて実装すればよいです。
    > List<Data>型として公開したいのであれば提示されたようにしてもよいと思います。
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63713  Re[3]: Listデータの隠蔽の方法
□投稿者/ επιστημη -(2012/09/30(Sun) 15:51:29)
>
    > 呼び元で、foreachを使いたい場合は、List<Data>型として公開する必要があるので、
    > その場合は他に方法はないですかね?

    foreachしたいだけなら IEnumerable<Data>
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63715  Re[4]: Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 16:26:21)
    No63713 (επιστημη さん) に返信

    なるほど。確かに IEnumerable<Data> で良いですね。

    そして、要件にひとつ書き忘れていたことがあることに気づきました。
    private な _dataList を“外に見せたくない”と書きましたが、
    取得元でこのリストを編集されたくないのです。

    IEnumerable<Data> を返すメソッドを実装したとき、
    単純に return _dataList で良いのでしょうか?
    それだと参照が帰るので、取得元で編集できてしまいそうな気がするのですが。
    (編集できないのであれば、これで十分です)

    > foreachしたいだけなら IEnumerable<Data>
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63716  Re[5]: Listデータの隠蔽の方法
□投稿者/ επιστημη -(2012/09/30(Sun) 17:12:12)
>
    > IEnumerable<Data> を返すメソッドを実装したとき、
    > 単純に return _dataList で良いのでしょうか?
    > それだと参照が帰るので、取得元で編集できてしまいそうな気がするのですが。
    
    Dataの複製を返せば壊さずに済む
    ...ただし複製に対して変更をかけたとき
    コンパイル/実行時にエラーにできない
    
    using System;
    using System.Collections.Generic;
    
    // データの構造(I/Fとして用意)
    public class Data
    {
        public Data() { a = 0; b = 0; }
        public Data(Data d) { a = d.a; b = d.b; }
        public int a;
        public int b;
        public void print() { Console.WriteLine("{0},{1}", a, b); }
    }
    
    public class DataManager
    {
        private List<Data> _dataList = new List<Data>();
        public void Add(Data value) { _dataList.Add(value); }
        public IEnumerable<Data> contains() { foreach (Data d in _dataList) yield return new Data(d); } // 複製を返す
    }
    
    public class Program
    {
        public static void Main()
        {
            DataManager dm = new DataManager();
            dm.Add(new Data());
            dm.Add(new Data());
            foreach (Data d in dm.contains())
            {
                d.a = 100;
            }
            foreach (Data d in dm.contains())
            {
                d.print();
            }
        }
    }
    
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63719  Re[6]: Listデータの隠蔽の方法
□投稿者/ Azulean -(2012/09/30(Sun) 19:03:04)
    考え方を広げるヒントとしていくつか書いてみました。
    
    
    1.Data を読み取り専用にしてしまうとか。
    
    public class Data
    {
      public int a { get; private set; }
      public int b { get; private set; }
      public Data(int value1, int value2)
      {
        a = value1;
        b = value2;
      }
    }
    
    リストの値を書き換えたくなったら、リストに入れる参照自体を変える。
    
    _dataList[0] = new Data(1, 2);
    
    
    2.読み取り専用のインターフェースを作ってそれを見せるとか。
    (キャストされると書き換えられますが)
    
    interface IData
    {
      int a { get; }
      int b { get; }
    }
    
    class Data : IData
    {
      public int a { get; set; }
      public int b { get; set; }
    }
    
    IEnumerable<IData> で見せる。(C# 4.0 以上の 共変性 がないとコピーを作るハメになるが)
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63722  Re[7]: Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 21:31:28)
    No63719 (Azulean さん) に返信

    ご意見ありがとうございます。

    Dataを読み取り専用にする・読み取り専用のI/Fを用意する、
    そうですね、そのようなやり方もありますね。

    今回は要求に見合わないので見送らせて頂きました。
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63721  Re[6]: Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 21:27:57)
    No63716 (επιστημη さん) に返信

    サンプルもご呈示して頂き、ありがとうございます。
    参考にさせていただきます。

    やはり複製を返す必要があるのですね。

    yield return ... そういえば、ありましたね。
    普段使わないので忘れていました。
記事No.63710 のレス /過去ログ107より / 関連記事表示
削除チェック/

■63723  Re[1]: Listデータの隠蔽の方法
□投稿者/ 亜守 -(2012/09/30(Sun) 21:32:40)
    皆様、ご意見ありがとうございました。
    とりあえず今回はコピーを返す形で実装しようと思います。
記事No.63710 のレス / END /過去ログ107より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -