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

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

C# と VB.NET の入門サイト

Re[1]: Listデータの隠蔽の方法


(過去ログ 107 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■63710 / inTopicNo.1)  Listデータの隠蔽の方法
  
□投稿者/ 亜守 (1回)-(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を作成して返すくらいです。
他に良い方法があれば教えてください。

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

DataManagerにList<Data>の公開したいメソッドをすべて実装すればよいです。
List<Data>型として公開したいのであれば提示されたようにしてもよいと思います。
引用返信 編集キー/
■63712 / inTopicNo.3)  Re[2]: Listデータの隠蔽の方法
□投稿者/ 亜守 (2回)-(2012/09/30(Sun) 12:42:20)
No63711 (shu さん) に返信

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

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

> ■No63710 (亜守 さん) に返信
>
> DataManagerにList<Data>の公開したいメソッドをすべて実装すればよいです。
> List<Data>型として公開したいのであれば提示されたようにしてもよいと思います。
引用返信 編集キー/
■63713 / inTopicNo.4)  Re[3]: Listデータの隠蔽の方法
□投稿者/ επιστημη (13回)-(2012/09/30(Sun) 15:51:29)
επιστημη さんの Web サイト
> 呼び元で、foreachを使いたい場合は、List<Data>型として公開する必要があるので、
> その場合は他に方法はないですかね?

foreachしたいだけなら IEnumerable<Data>

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

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

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

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

> foreachしたいだけなら IEnumerable<Data>

引用返信 編集キー/
■63716 / inTopicNo.6)  Re[5]: Listデータの隠蔽の方法
□投稿者/ επιστημη (14回)-(2012/09/30(Sun) 17:12:12)
επιστημη さんの Web サイト
> 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();
        }
    }
}

引用返信 編集キー/
■63719 / inTopicNo.7)  Re[6]: Listデータの隠蔽の方法
□投稿者/ Azulean (45回)-(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 以上の 共変性 がないとコピーを作るハメになるが)

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

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

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

yield return ... そういえば、ありましたね。
普段使わないので忘れていました。

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

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

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

今回は要求に見合わないので見送らせて頂きました。

引用返信 編集キー/
■63723 / inTopicNo.10)  Re[1]: Listデータの隠蔽の方法
□投稿者/ 亜守 (6回)-(2012/09/30(Sun) 21:32:40)
皆様、ご意見ありがとうございました。
とりあえず今回はコピーを返す形で実装しようと思います。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -