10

Cを使用して実装するのに慣れているものの簡単な例を示します。私が考える焦点は、データをどのように使用できるかであり、例で何をしているのかということではありません:)

typedef struct  
{
  const char  *description;
  uint32_t    colour_id;      
  uint32_t    quantity;
} my_data_t;

const my_data_t ref_data[] =
{
  {"Brown Bear", 0x88,   10},
  {"Blue Horse", 0x666,  42},
  {"Purple Cat", 123456, 50},
};

void show_animals( void )
{
  my_data_t *ptr;

  ptr = &ref_data[2];

  console_write("Animal: %s, Colour: 0x%8X, Num: %d", 
      ptr->description,
      ptr->colour_id,
      ptr->quantity);
}

そこで、同様のデータ テーブルまたは参照データを C# で実装する方法についてアドバイスを求めています。私は物事のより高いレベルの側面についてコツをつかんでいますが、まだテーブル駆動型のデータ メソッドを扱っていません。

例として、私が C# でやろうとしているのは、説明フィールドから選択できるコンボ ボックスを作成し、色 ID数量を使用して読み取り専用ボックスを更新することです。

これは非常に単純な例ですが、それを実装する良い方法を判断できれば、実際に行っていることに当てはめることができます。

4

3 に答える 3

4

ReadOnlyCollection<T>不変クラスのa を使用します。

public class MyData
{
    public MyData(string description, int colorId, int quantity)
    {
        Description = description;
        ColorId = colorId;
        Quantity = quantity;
    }
    public string Description {get; private set; }
    public int ColorId {get; private set; }
    public int Quantity {get; private set; }
}


...

public static readonly ReadOnlyCollection<MyData> refData =
    new ReadOnlyCollection<MyData>(
        new [] {
            new MyData("Brown Bear", 0x88,   10),
            new MyData("Blue Horse", 0x666,  42),
            new MyData("Purple Cat", 123456, 50)
            });
于 2012-12-11T20:49:19.460 に答える
2

これ

const my_data_t ref_data[] =
{
  {"Brown Bear", 0x88,   10},
  {"Blue Horse", 0x666,  42},
  {"Purple Cat", 123456, 50},
};

のようなreadonly修飾子で置き換えることができますC#

//INITIALIZED ONES AND NEVER CHANGED, BY CONVENTION
public static readonly ref_data[] my_data_t = new ref_data[] =
{
  new ref_data{Animal = "Brown Bear", Code = 0x88,   Index = 10},
  new ref_data{Animal = "Blue Horse", Code = 0x666,  Index = 42},
  new ref_data{Animal = "Purple Cat", Code = 123456, index = 50},
};

どこref_data(この場合)は次のようなものです

public class ref_data
{
   public string Animal {get;set;}
   public int    Code   {get;set;}  //GUESS, PUT APPROPRIATE NAME
   public int    Index  {get;set;}  //GUESS, PUT APPROPRIATE NAME
}

同じことが定数const char *description、使用にも当てはまりますreadonly

繰り返しますが、これは慣習によるものです。理論的には、データを変更したり、データへのアクセスをだます方法があるからです。

ガベージ コレクターは、メモリの断片化を回避するためにメモリを継続的に縮小 (デフラグ) するため、(マネージ メモリ内の) ポインタは常に周囲を移動するため、定数ポインタの概念はありません。これにより、高速割り当ての利点が得られます。C#

別のオプションもあります(これがあなたのケースに適しているかどうかはわかりません)。修飾子を介してコードへの管理されていないアクセスを使用し、すべてのポインターを内部に保持できます。このようにして、Grabage Collector に「待ってください。自分が何をしているのかわかっています」と言うので、通常のコードを記述しているかのように、すべてのメモリ管理を (そのアンマネージコード内で) 処理する必要があります。unsafeC/C++C/C++

于 2012-12-11T20:31:29.913 に答える
1

ジョーの回答で私のコメントについて詳しく説明するというあなたの要求に応えて、この回答を投稿しています。

my_data_t最初のポイント:何らかの理由で構造体にする必要がある場合、C# はそれらをサポートします。必要でない限り、Joe が行ったようにクラスにアップグレードする必要はありません。

public struct MyData
{
    public string Description;
    public uint ColourID;
    public uint Quantity;
} 

これは変更可能な構造体です。この構造体のインスタンスが与えられた場合、必要に応じてその値を変更できます。ほとんどの人は、変更可能な構造体は悪だと言うでしょう。ゲーム開発者として、可変構造体は非常に重要であると同時に危険でもあると言えます。

任意のオブジェクトの変更可能なフィールドとプロパティは、オブジェクト初期化構文を使用して初期化できます。これはおそらく、C で行っていることと最も類似しています。

MyData x = { Description = "Brown Bear", ColourID = 0x88, Quantity = 10 };

個人的には、特に大きな構造体の場合、これは少し扱いに​​くいと思いますが、使用したい場合は利用できます。

readonlyフィールドに修飾子を追加することで、構造体を不変に変更できます。

public struct MyData
{
    public MyData(string description, uint colourID, uint quantity)
    {
        this.Description = description;
        this.ColourID = colourID;
        this.Quantity = quantity;
    }
    public readonly string Description;
    public readonly uint ColourID;
    public readonly uint Quantity;
} 

readonlyオブジェクト参照が変更されないようにするだけであることに注意してください。オブジェクトが変更可能であれば、オブジェクト自体が変更されるのを防ぐことはできません。

また、コンストラクターも追加したことに注意してください。これは、readonlyフィールドは静的初期化子またはオブジェクトのコンストラクターの内部でのみ設定できるためです (トリックを除けば)。MyDataここでは、Joe の回答のように新しいインスタンスを初期化します。

MyData x = new MyData("Brown Bear", 0x88, 10);

2 番目のポイント: 一貫性、またはその欠如。C スタイルの constness が壊れているため、C# は C スタイルの constness をサポートしていません。Microsoft の C# 言語チームの元開発者である Eric Lippert は、ここでその点について詳しく説明しています。

本当に、本当に、本当に正当な理由がない限り、C スタイルの constness をエミュレートすることについて心配しない方がはるかに良いと思います。Constness は最終的に、悪意のある人や無知な人によってコードが改ざんされるのを防ぐ方法です。悪意のある人は、あなたが好むと好まざるとにかかわらず、C や C# でデータを変更できるようになります。そして、他者の無知から身を守るためのはるかに優れたツールがあります: カプセル化です!

このテーブルを使用する機能をクラス内にラップし、テーブルをそのクラスのプライベート メンバーにしてから変更しないでください。ある時点でそのテーブルを外の世界に公開する必要がある場合ReadOnlyCollection、Joe が提案したように使用できます。

public static readonly ReadOnlyCollection<MyData> ReferenceTable = new ReadOnlyCollection<MyData>(new []
{
    new MyData(/* whatever */),
    new MyData(/* whatever */),
    new MyData(/* whatever */),
});

ReadOnlyCollection他のコレクション (この場合はデータ テーブル) の薄いラッパーです。IList<T>配列といくつかの組み込みコレクションを含む、インターフェイス を実装する任意のオブジェクトをラップできます。

もう1つの注意:あなたのコメントの1つで、constCでテーブルを宣言する理由の1つは、オブジェクトがメモリ内のどこに割り当てられるかに影響するためだと述べました。ここではそうではありません。上記の例でRefDataは、マネージド ヒープで宣言されます。これは配列であり、配列は参照型であるためです。

于 2012-12-12T15:37:08.237 に答える