人に聞けない痔の悩み、これでスッキリ >>

2次元配列double[,] sample = new double[0,0]の要素数を動的にしたいです。
1次元配列ならArray.Resize(ref sample, int length);とかでできますがArray.Resizeは2次元に対応していないためこの方法が使えなくて困っています。
なるべくListを使いたくないのですがどうにかできないでしょうか?
やはりポインタを使うべきでしょうか?

A 回答 (4件)

何故Listを使いたくないのでしょうか?


これによって対処が随分変わります。

Object型になるのが嫌であればジェネリクスのList型もあります。
■List<T> クラス
https://msdn.microsoft.com/ja-jp/library/6sh2ey19(v=vs.110).aspx

またパフォーマンス面であればArrayのResizeはするべきではありません。
新規の配列を確保して全データのコピーが行われるため大変重いです。

■ArrayクラスResizeの内部処理
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public static void Resize<T>(ref T[] array, int newSize) {
if (newSize < 0)
throw new ArgumentOutOfRangeException("newSize", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
Contract.Ensures(Contract.ValueAtReturn(out array) != null);
Contract.Ensures(Contract.ValueAtReturn(out array).Length == newSize);
Contract.EndContractBlock();

T[] larray = array;
if (larray == null) {
array = new T[newSize];
return;
}

if (larray.Length != newSize) {
T[] newArray = new T[newSize];
Array.Copy(larray, 0, newArray, 0, larray.Length > newSize? newSize : larray.Length);
array = newArray;
}
}

またポインタで実装するにしても単純な配列であれば、連続してメモリ上に確保できないためリサイズした時にコピーが必要になります。
コピー不要なリサイズ可能な配列な様なものを実装するとなるとリスト構造を自分で作ることになります。
.NETのList配列は10年以上の時間をかけてとてもよく練り上げられたソースになっています。
それ以上のパフォーマンスを出す事はとても難しいでしょう。
もちろん、Listであればジャグ配列ならぬジャグリストになるところを最初から二次元リストとして実装できるのでそこの部分は有利であり、Listよりパフォーマンスをよくする事が全く不可能とは言いませんがとても難しい事です。
ただ、そこまでパフォーマンスを考えるのであれば、固定長の配列になるように仕様を変えてしまった方が良いでしょう。

また、何らかの理由で二次元配列しか受け取らないメソッドを呼び出すのであれば、ListのToArrayメソッドを利用するとよいでしょう。
長さの変わる間はList型で動かし、確定した時点で配列に変換する事で、長さが変わる度にコピーしていたものが1度のみのコピーで済ませられます。

最後に…もし…パラメータの配列長等に合わせて配列を定義したいのであれば以下の様な事も可能です。
double[,] sample = new double[param1.Length,param2.Length]
    • good
    • 1

Listでジャグすれば良いだけでは?


自前で実装した方がずっと面倒。
間違いなく車輪の再発明になります。
    • good
    • 0

配列コピーすればいいんじゃないですか?


http://www.atmarkit.co.jp/ait/spv/1704/26/news02 …

なんでList<T>を嫌うのか不明ですが。
    • good
    • 0

ポインタについては勉強不足でわかりませんけど、Listクラスを使いたくないという事はArrayListもダメという事でしょうか?


まぁ、この場合やろうとしてるのは2次元配列ではなく『配列の配列』ですけれど。
たまにExcelでやっているもので。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aと関連する良く見られている質問

QC#にて別クラスの関数を使いたい

C#にて、別クラスの関数を使用する方法を教えてほしいです。

下記のような、構造体を受け取るメソッドを作りました。

*****************************
private struct MyPoint
{
public int x;
public int y;
}

private void proc1(MyPoint pt)
{
MessageBox.Show("座標:" ; pt.x + "," + pt.y + "実行結果");
}

private void button1_Click(object sender ,System.EventArgs e)
{

MyPoint pt;
pt.x = 10;
pt.y = 20;
proc(pt);
}
*****************************

別のフォームのクラスから、proc1を呼び出したいのですが、やり方がわかりません。
どうか、教えてください。

Aベストアンサー

同じ定義をしたとしても別の名前空間に書いた構造体は同一とはみなされません。

呼び出し先クラスでの構造体を private では無く、public で宣言して下さい。

呼び出し元では、

MyClass.MyPoint pt;

のようにして実体を作ります。

QC#で共有変数の定義をするには

C#で共有変数の定義をするには、どうしたらよいでしょうか。具体的には、起動パラメータで、任意の文字列(3~4バイト)を渡して、C#アプリケーションを、起動し、プログラムの任意の場所で、そのパラメータを参照したいと考えています。起動パラメータの受け取りは、できるのですが、そのパラメータを、プログラムのどこからも参照できる領域(ここの定義方法が不明)に格納するには、どうしたらよいでしょうか。(2重起動を許す前提です。実行時に1つの目のプログラムにはパラメータ"XYZ"を渡し、2つ目のプログラムを起動時にはパラメータ"ABCD"を渡し、その値により、プログラムの動作を制御したいと思っています)
Windows-xp visual-studio2008 C#でwindowsアプリケーションを作成しています。

Aベストアンサー

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(new Form1());
    }
    // ここに記述
    static public string strArg = null;
  }
}

メインクラスのメンバーとしてスコープが有効な場所に記述します

namespace test1
{
  static class Program
  {
    /// <summary>
    /// アプリケーションのメイン エントリ ポイントです。
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
      if (args.Length > 0)
      {
        strArg = args[0];
      }
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Application.Run(n...続きを読む

QC# ArrayListを二次元配列のように使用したい。

C#についての質問です。

現在、ArrayListを用いた情報管理リストのプログラムを作成しています。
そのプログラムにソートを行う機能と、検索機能をつけたいのですが、そこで質問です。
ArrayList内の要素を、「特定のフィールド(例えば氏名であったり、年齢であったりするのですが…)を基準として昇順または降順にソートする」という処理、またあるフィールドのみを基準に検索を行うという処理を行う際、ArrayListを二次元配列のように使用することが出来たら便利だな、と思ったのですが、そのようなことは可能でしょうか?

いろいろと試したり、独自に調べてはみたのですが、いまいちわからず、質問させていただきました。

お分かりになられる方がいらっしゃいましたら、ご教授いただければと思います。
よろしくお願いいたします。

Aベストアンサー

ArrayListを継承した独自のクラスを定義して[]のインデクサを定義すれば可能でしょう

class Person {
  private string name;
  private int age;
  Person( string sName, int nAge ) {
    Name = sName;
    Age = sAge;
  }
  public Name {
    get { return name; }
    set ( name = value; }
  }
  public Age {
    get { return age; }
    set { age = value; }
  }
}

class myAL : ArrayList
{
  public virtual object this[ int nIndex, int nType ] {
    get {
      object obj = this[nindex];
      // Namespaceは実際のNamesapceに置換してください
      if ( obj.GetTye() == Type.GetType( "NameSpace.Person" ) ) {
        Person p = (Person)obj;
        switch( nType ) {
        case 0:
          return p.Name;
        case 1:
          return p.Age;
        }
      }
      // nTypeが0または1以外 および objがPerson以外の型
      return null;
    }
  }
}
といった具合の実装で ・・・

ArrayListを継承した独自のクラスを定義して[]のインデクサを定義すれば可能でしょう

class Person {
  private string name;
  private int age;
  Person( string sName, int nAge ) {
    Name = sName;
    Age = sAge;
  }
  public Name {
    get { return name; }
    set ( name = value; }
  }
  public Age {
    get { return age; }
    set { age = value; }
  }
}

class myAL : ArrayList
{
  public virtual object this[ int ...続きを読む

QC#での動的配列作成方法について

はじめまして、

現在ASP.NET、C#で開発をしております。
そこで、質問です。

C#で二次元配列を作成し、データを格納します。
二次元配列は宣言時はサイズがわかってません。
ループで回った回数分、最初(第一要素数)の要素数が決定します。
二つ目の要素数の数は最初からきまっています(固定用素数)。

string[][]
string[,]
arraylist
などがあると思いますが、上記の場合どういう風に配列を作成していったらいいのでしょうか?
動的にサイズを変更できる配列の作り方、データ格納方法、データ表示方法を教えてください。

よろしくお願いします。

Aベストアンサー

//例えば、こんな感じ
using System;
using System.Collections;
public class SamplesArrayList {

public static void Main() {

ArrayList aArrayList = new ArrayList();
for(int i=0;i<10;i++){
aArrayList.Add(new int[5]); // ArrayListへの追加(intに限らない)
for(int j=0;j<5;j++){
((int[])aArrayList[i])[j]=i+j;// 値のセット
}
}
// 表示
Console.WriteLine( "aArrayList" );
Console.Write( "データ数:{0}\n", aArrayList.Count );
for(int i=0;i<aArrayList.Count;i++){
Console.Write( "\nデータ[{0}]:\n\t",i);
for(int j=0;j<5;j++){
Console.Write("[{0}]", ((int[])aArrayList[i])[j] );
}
}
}
}
ArrayListを使うことで動的な配列を作成できます。
サンプルでは、回数が決まっていますが、回数のループが決まっていない時にも、使えるのは明白です。
ArrayListには、addメソッドを使ってオブジェクトという形でなんでも格納できます(サンプルではintの配列)アクセスには、[]が使えます。詳しくは、ヘルプを参照して下さい。

//例えば、こんな感じ
using System;
using System.Collections;
public class SamplesArrayList {

public static void Main() {

ArrayList aArrayList = new ArrayList();
for(int i=0;i<10;i++){
aArrayList.Add(new int[5]); // ArrayListへの追加(intに限らない)
for(int j=0;j<5;j++){
((int[])aArrayList[i])[j]=i+j;// 値のセット
}
}
// 表示
Console.WriteLine( "aArrayList" );
Console.Wri...続きを読む

QCloseとDisposeの違い

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、...続きを読む

Aベストアンサー

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリ...続きを読む

QC#でほかのファイルにある自作クラスを使用したい場合

最近Javaから移ってきたばかりのC#初心者です。
依然作ったことのあるほかのファイルにある自作クラスを
新しいファイルの自作クラスで使用したい場合、どうすれば
よいのでしょうか。
Form1.cs(8,7): error CS0246: 型または名前空間名 'Calc1' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
Form1.cs(12,19): error CS0246: 型または名前空間名 'Calc' が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。
上記のようなエラーが発生してしまいます。
なにとぞご助力をお願いいたします。

Aベストアンサー

#2>しかし、やはりうまくいきませんでした。
#1で言われているような、namespace, using 指定と参照設定でうまくいくと思うんですけど・

自作クラスを補足することはできますか?

QDataTableから条件を満たした行を別のDatatableへコピーしたい

VC#2005とSQLServer2005ExpressEditionでWindowsアプリケーションを作成しています。

データベースの中から1つのマスタテーブルのデータを呼び出すのにTableAdapterを使ってDataTableにデータをバインドしました。
そこから条件を満たしている行をすべて抽出して同じ型のDataTableにデータをコピーしたいのです。

ですから、DataTableは2つ用意しています。1つは上記の通りデータをバインドしていますが、もう1つは宣言しただけなのでまだ空っぽの状態です。
DataTableにはカラムが3列あり、その中の1列をグループIDとしています。
条件としてはグループIDが同じであるということです。
やりたいことは条件を満たしている行をすべて抽出して空のデータテーブルにコピーすることです。

どなたかご存知の方いらっしゃれば教えてください。
よろしくお願いします。

Aベストアンサー

C#だったんですね … さほど変わりないと思いますが

お使いのコードが提示されていないのでこちらで適当な変数をでっち上げております
現在お使いのコードを支障の無い範囲で提示しましょう

//元のデータテーブルがdtSourceとすると
// テーブル構造をコピー
DataTable dt = dtSource.Clone();
DataRow r = null;
foreach( DataRow dtRow in dtSource.Select("選択するための文字列"))
{
  r = dt.NewRow();
  for( int n = 0; n < dtRow.ItemArray.Length; n++ )
  {
    r[n] = dtRow[n];
  }
  dt.Rows.Add( r );
}
といった具合になると思います

# 前回の投稿中のstSorceはdtSourceの単なるミスです

QC# 計算処理中に実行中ウィンドウを表示させたい。

アドバイスをお願いいたします。

やりたいこと:
(1)メインウィンドウで「計算始めるボタン」を押す。
(2)すると計算中には「実行中」の文字が別ウィンドウで立ち上がる。
(3)計算が終わると別ウィンドウが閉じる。

下記プログラムの不具合:
別ウィンドウで「実行中」の文字を出させたいが、文字部分が描画されない。

注意: 
下記プログラムはAthlon3000+で1秒ほどかかります。
CPUが遅いマシンで試す場合は「//計算処理」部分のfor重みを軽減させて実行して下さい。

using System;
using System.Drawing;
using System.Windows.Forms;

//メインウィンドウ
public class MainForm : Form {
private Button button;
private Label label;
public MainForm() {
button = new Button();
button.Text = "計算GO!!";
button.Click += new System.EventHandler(button_click);
label = new Label();
label.Location = new Point(50,50);
label.Text = "メインウィンドウ!";
Controls.Add(button);
Controls.Add(label);
Text = "MainForm";
BackColor = Color.Blue;
}

static void Main() {
Application.Run(new MainForm());
}

//計算GOボタンをクリックした時の処理
private void button_click(object sender, System.EventArgs e) {
double z;
SubForm Sub = new SubForm();

Sub.Show();

//計算処理
for(int i=0; i<=500000000; i++)
z = double.MaxValue * double.MinValue;

Sub.Close();

MessageBox.Show("計算終了");
}
}

//計算中を通知するウィンドウ
public class SubForm : Form {
private Label label;
public SubForm(){
label = new Label();
label.Text = "実行中!";
label.Location = new Point(50,50);
Text = "計算中通知ウィンドウ";
BackColor = Color.Red;
Controls.Add(label);
}
}

アドバイスをお願いいたします。

やりたいこと:
(1)メインウィンドウで「計算始めるボタン」を押す。
(2)すると計算中には「実行中」の文字が別ウィンドウで立ち上がる。
(3)計算が終わると別ウィンドウが閉じる。

下記プログラムの不具合:
別ウィンドウで「実行中」の文字を出させたいが、文字部分が描画されない。

注意: 
下記プログラムはAthlon3000+で1秒ほどかかります。
CPUが遅いマシンで試す場合は「//計算処理」部分のfor重みを軽減させて実行して下さい。

using System;
using S...続きを読む

Aベストアンサー

このような場合はマルチスレッドにするのが常套手段だと思います。

例えば、ボタン押した時にウインドウを作成表示し、計算スレッドを起動。計算スレッドの終了時にウインドウを閉じるのような動作にします。
逆に、Formの方を新規のスレッドにする手もありますが。

WIN32 API呼び出すより楽です。

[HOWTO] Visual C# .NET を使用してスレッドを作成する方法
http://support.microsoft.com/default.aspx?scid=kb;ja;815804

C#プログラミング入門 第7回:マルチスレッドプログラミング
http://www.stackasterisk.jp/tech/dotNet/csharp07_02.jsp

参考URL:http://www.stackasterisk.jp/tech/dotNet/csharp07_02.jsp

Qフルパスから最後のディレクトリ名を取得したい。

vb.netなのですが、例えば
c:\aaa\bbb\ccc\ddd\eee\fff.exe
というフルパスがあったとして、
eeeというディレクトリ名を取得したいのですが、
何か良い方法はないでしょうか。
それぞれのディレクトリ名の文字数や階層数は
決まっていないのですが、オススメの方法が
ありましたら、教えて頂けると助かります。

Aベストアンサー

MessageBox.Show(IO.Path.GetFileName(IO.Path.GetDirectoryName(myPath)))

IO.Path の GetDirectoryName でフォルダのフルパスを取得して、さらに IO.Path の GetFileName で最終フォルダ(またはファイル)の名前を取得。

QC#で構造体の配列を持った構造体を使いたいのですが

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するには、次元指定子を変数の識別子の前に指定します。固定サイズ バッファ フィールドを宣言するには、フィールド型の前に fixed キーワードを使用します
となり

fixed をつけると

固定サイズ バッファの型は次のうちの 1 つでなければなりません: bool、byte、short、int、long、char、sbyte、ushort、uint、ulong、float または double

となってしまいます

C#で構造体の配列を持った構造体を使いたいのですが
Cならば
struct xyz {
struct abc _abc[32];
int index;
};
struct abc {
int a;
int b;
int c;
};

struct xyz _xyz[8];
xyz[0]._abc[3].b = 1;

のような使い方で という感じで やっていた事を C#で 同じような事をやろうとしても うまくいきません
うまくやる方法をどなたかご存知ないでしょうか

Visual Studio 2005行った場合
コンパイルで
構文エラーです。不適切な配列の宣言子です。マネージ配列を宣言するに...続きを読む

Aベストアンサー

C# では、配列は「単なる連続したメモリ領域」ではなくて「添字によってオブジェクトを格納できるオブジェクト」であることに注意しなくてはいけません。つまり、C では配列は一種の構造体でしたが、C# では配列は参照型のオブジェクトです。
よって、C のように予めサイズを固定しておくということは基本的にできません。配列の大きさは配列のインスタンスが作られるときに動的に決まります。

C# では、参照型のオブジェクトを構造体のメンバにすることはあまりありません。null 値の扱いが面倒だからです。
また、C# では構造体の大きさは大きくとも 20 バイト程度までにします。C# では基本的に「構造体へのポインタ」はありません。巨大な構造体をそのまま扱うのはメモリの使い方の観点からいって非効率的です。

今回の件では、構造体ではなくクラスにするのがよいかと思われます。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング