DOBON.NET DOBON.NETプログラミング掲示板過去ログ

C#でVB6のような構造体の動的配列

環境/言語:[windows2000、C#]
分類:[.NET]

いつも参考にさせていただいています。
C#について1つ質問させて下さい。
VB6での下記のような構造体の動的配列のようなことを、
C#で実現できるのでしょうか??
実現方法は構造体でもクラスでも構いません。

Module1

Type A
intSample as Integer
strSample as String
End Type
Public SampleData() as A

Form1のForm Load

Redim SampleData(1)

SampleData(1).intSample = 111
SampleData(1).strSample = "ああああ"

Form1の登録ボタンクリックイベント

Redim Preserve SampleData(Ubound(SampleData)+1)
SampleData(Ubound(SampleData)).intSample = 222
SampleData(Ubound(SampleData)).strSample = "いいいい"

大まかに上記のような処理です。
(登録ボタンを押すたびに配列を1つずつ増やすイメージです)
どうしても実現方法がわからなくて悩んでいます。
どなたかお判りになる方がおられましたらご教授いただけます
でしょうか。よろしくお願いいたします。
■No6421に返信(mitaさんの記事)
> いつも参考にさせていただいています。
> C#について1つ質問させて下さい。
> VB6での下記のような構造体の動的配列のようなことを、
> C#で実現できるのでしょうか??
> 実現方法は構造体でもクラスでも構いません。

> どうしても実現方法がわからなくて悩んでいます。
> どなたかお判りになる方がおられましたらご教授いただけます
> でしょうか。よろしくお願いいたします。

サイトを利用する前に、そのサイトのTipsくらい目を通そうよ。
http://dobon.net/vb/dotnet/vb2cs/redimpreserve.html
■No6422に返信(java.lang.Nullpoさんの記事)
> ■No6421に返信(mitaさんの記事)
>>いつも参考にさせていただいています。
>>C#について1つ質問させて下さい。
>>VB6での下記のような構造体の動的配列のようなことを、
>>C#で実現できるのでしょうか??
>>実現方法は構造体でもクラスでも構いません。
>
>>どうしても実現方法がわからなくて悩んでいます。
>>どなたかお判りになる方がおられましたらご教授いただけます
>>でしょうか。よろしくお願いいたします。
>
> サイトを利用する前に、そのサイトのTipsくらい目を通そうよ。
> http://dobon.net/vb/dotnet/vb2cs/redimpreserve.html

ご指摘のサイトのTipsは事前に拝見した上で質問させていただきました。
普通の1次元配列のようなものは確かにわかったのですが、私が
どうしてもわからないのは構造体での動的配列です。
お手数ですがよろしくお願いいたします。
■No6423に返信(mitaさんの記事)
> ご指摘のサイトのTipsは事前に拝見した上で質問させていただきました。
> 普通の1次元配列のようなものは確かにわかったのですが、私が
> どうしてもわからないのは構造体での動的配列です。
> お手数ですがよろしくお願いいたします。

リンク先と同じ手口で伸ばすことできたんだけどなぁ。
で、使いやすく関数化するとこうなるのかなぁ。

private void button1_Click(object sender, EventArgs e) {
    StructHoge[] tSource = new StructHoge[15];
    StructHoge[] tDest;

    for (int i = 0; i <= 14; i++) {
        tSource[i].Code = (i + 1) * i;
        tSource[i].Name = "名前" + i.ToString();
    }

    tDest = ReDimPreserveStructHoge(tSource, 20);
}

private StructHoge[] ReDimPreserveStructHoge(StructHoge[] tSource, int iSize) {
    StructHoge[] tReturn;
    int          iLength;

    if (tSource == null) {
        return null;
    }

    tReturn = new StructHoge[iSize];
    iLength = tSource.Length;

    if (iLength > iSize) {
        iLength = iSize;
    }

    Array.Copy(tSource, tReturn, iLength);

    return tReturn;
}

# それとも、もっと高度なことでしたか?
■No6424に返信(java.lang.Nullpoさんの記事)
> ■No6423に返信(mitaさんの記事)

ご丁寧な解説ありがとうございました。
配列自体を増やす処理はわかりました。
ちょっと質問の意図と外れてしまうのですが、例えば一連の処理を
Form1というクラスで処理するとして、Form1のロード処理で
先程の解説いただいた例だと

> StructHoge[] tSource = new StructHoge[15];

を記述し、ボタンのクリックイベントで

> StructHoge[] tDest;
> tDest = ReDimPreserveStructHoge(tSource, 20);

みたいなことは出来るのでしょうか??
(Form1のクラスレベルの変数として、tSourceを定義できる
のでしょうか??)

C#を始めたばかりで変な質問になってしまっているような気も
するのですが、もしこのような質問でおわかりになれば
教えていただけますか。
(VB6でいうと、フォームモジュールのモジュールレベル変数として
構造体変数を定義して、フォームロードでその変数に初期値を代入し、
ボタンクリックでその変数に加算していく、という処理をしたい
のです)

よろしくお願いいたします。
■No6429に返信(mitaさんの記事)
> (Form1のクラスレベルの変数として、tSourceを定義できる
> のでしょうか??)

アクセシビリティの概念をお勉強されることをお勧めしますが、お答えします。
私のソースですと、ローカルスコープ変数なのはお判りになられますでしょうか?
ローカルスコープということは、そのメソッド内でしか参照できません。
「Form1のクラスレベル」というのは、モジュール変数(Form1のプライベートな変数)となります。

ですので、

> Form1というクラスで処理するとして、Form1のロード処理で
> StructHoge[] tSource = new StructHoge[15];
> を記述し、ボタンのクリックイベントで
> StructHoge[] tDest;
> tDest = ReDimPreserveStructHoge(tSource, 20);
> 
> みたいなことは出来るのでしょうか??

当然、簡単にできます。
これはtSourceをメソッド外に追い出せばよいのです。

> (VB6でいうと、フォームモジュールのモジュールレベル変数として
> 構造体変数を定義して、フォームロードでその変数に初期値を代入し、
> ボタンクリックでその変数に加算していく、という処理をしたい
> のです)

よく判っていらっしゃるではないですか。
そういうことです。

一応、Button1を押下することでどんどん配列の要素が増えるサンプルソースを載せておきますね。

Source:-------------------------------------------------------------------

internal class FormMain : System.Windows.Forms.Form {

    /* プライベート メンバ 変数として定義 */
    private StructHoge[] m_tHoge = new StructHoge[0];

  /* m_tHogeの配列を1つずつ伸ばすButton */
    private void button1_Click(object sender, EventArgs e) {
        m_tHoge = ReDimPreserveStructHoge(m_tHoge, m_tHoge.Length + 1)
    }

}

--------------------------------------------------------------------------
ちなみに先ほどの配列を伸ばすメソッドですが、以下のようにすべきでした。
未割当ての場合は、nullを返すのではなく、伸ばした結果を返すべきでした。m(_ _)m
また、この関数、Array型でできると汎用性が広がるんですが...。
キャストが巧く出来ないようで...残念。

Source:-------------------------------------------------------------------

    private StructHoge[] ReDimPreserveStructHoge(StructHoge[] tSource, int iSize) {
        StructHoge[] tReturn;
        int iLength;

        if (tSource == null) {
            return new StructHoge[iSize];
        }

        tReturn = new StructHoge[iSize];
        iLength = tSource.Length;

        if (iLength > iSize) {
            iLength = iSize;
        }

        Array.Copy(tSource, tReturn, iLength);
        return tReturn;
    }

--------------------------------------------------------------------------
> また、この関数、Array型でできると汎用性が広がるんですが...。
> キャストが巧く出来ないようで...残念。

こんな感じで、できないことはないですが、ArrayListなどのコレクション
を使う方が、いいと思います(^^;

private Array myReDim(Array tSource, int iSize)
{
  Array tReturn = Array.CreateInstance(tSource.GetType().GetElementType(), iSize);

  if (tSource == null)
    return tReturn;

  int iLength = tSource.Length;

  if (iLength > iSize)
    iLength = iSize;

  Array.Copy(tSource, tReturn, iLength);
  return tReturn;
}

private void button1_Click(object sender, System.EventArgs e)
{
  hoge = (StructHoge[])myReDim(hoge, hoge.Length + 1);
}
■No6433に返信(antさんの記事)
java.lang.Nullpoさん、antさん、ご回答ありがとうございます。
おかげさまでやりたいことが実現出来ました。
本当にありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板