●C#とは? 簡単に紹介
C#は、マイクロソフトが開発した多機能なプログラミング言語です。オブジェクト指向プログラミングを採用し、Javaと似た文法を持っています。
C#は.NET Frameworkの中核をなし、WindowsやWebアプリケーション、ゲームなど幅広い分野で活用されています。
初心者にも学びやすく、エンタープライズレベルの開発にも適しているのが特徴です。
C#を学ぶことで、効率的で堅牢なアプリケーションを開発するスキルが身につきます。
データベース操作、ネットワークプログラミング、ユーザーインターフェースデザインなど、様々な分野でC#の知識が役立ちます。
またUnityゲームエンジンでもC#が使用されており、ゲーム開発への応用も可能です。
C#は長年にわたって進化を続け、現在ではC# 12までのバージョンがリリースされています。
最新のバージョンでは、より簡潔で読みやすいコードが書けるように改良が加えられています。
例えば、レコード型や非NULLの参照型など、生産性を高める新機能が追加されました。
○C#の基本概念
C#を学ぶ上で、基本概念を理解しておくことはとても大切です。
まずは、変数とデータ型の概念です。
変数は値を格納するための名前付きの領域で、整数型のintや文字列型のstringなど、様々なデータ型があります。
変数を宣言する際は、適切なデータ型を選択し、意味のある名前をつけるようにしましょう。
続いて、制御構文について理解を深めましょう。
if文による条件分岐、for文や while文などの繰り返し処理は、プログラムの流れを制御するための基本的な構文です。
これを効果的に使いこなすことで、様々な処理を実現できます。
C#はオブジェクト指向言語ですから、クラスとオブジェクトの概念も重要です。
クラスは、関連するデータとメソッドをひとまとめにした設計図のようなものです。
そのクラスから生成されるのがオブジェクトで、プログラム内で実際に動作する実体です。
カプセル化、継承、ポリモーフィズムなどのオブジェクト指向の原則を理解し、適切にクラスを設計することが求められます。
例外処理も欠かせない概念です。
ランタイムエラーが発生した際に、try-catch文を使って例外をキャッチし、適切に処理を行うことができ、プログラムの安定性と信頼性が向上します。
こうした基本概念をしっかりと身につけることが、C#プログラミングの第一歩と言えるでしょう。
●DataTableとDataRowの基礎
C#でデータを扱う際に欠かせないのが、DataTableとDataRowです。
この2つのクラスを使いこなすことで、効率的なデータ操作が可能になります。
まずは、それぞれの役割と特徴を見ていきましょう。
○DataTableとは何か?
DataTableは、データを表形式で保持するためのクラスです。
表の各列はDataColumnオブジェクトで表現され、各行はDataRowオブジェクトで表現されます。
DataTableは、メモリ上でデータを管理するための便利な機能を提供しており、データベースから取得したデータを一時的に格納したり、複雑な計算を行ったりするのに適しています。
DataTableの主な特徴として、後述のような点が挙げられます。
- 列の追加、削除、変更が容易
- 行の追加、削除、編集が容易
- データの検索、ソート、フィルタリングが可能
- 他のデータソースとの連携が簡単
初めてDataTableを使う際は、少し戸惑うかもしれません。
しかし、その基本的な構造を理解すれば、データ操作の幅が大きく広がるはずです。
実際のコードを書きながら、DataTableの使い方を身につけていきましょう。
○DataRowの特徴と利用シナリオ
DataRowは、DataTable内の1行分のデータを表すクラスです。
各列の値は、DataRowの属性として保持されます。
DataRowを使って、次のようなことができます。
- 新しい行の追加
- 既存の行の値の変更
- 行の削除
- 行のコピーや移動
DataRowは、データバインディングにも利用されます。
つまり、DataRowのデータを直接UIコントロールに表示したり、UIコントロールの変更をDataRowに反映したりできるのです。
これにより、データとUIの同期が容易になります。
また、DataRowは、DataTableの検索やフィルタリングの際にも重要な役割を果たします。
特定の条件を満たすDataRowを見つけ出したり、DataRowの値を基にデータを絞り込んだりできます。
●DataRowをDataTableに追加する5つの方法
さて、DataTableとDataRowの基本的な概念は理解できたでしょうか。
では早速、DataRowをDataTableに追加する方法を見ていきましょう。
C#では、複数の方法でDataRowを追加できるので、状況に応じて適切な方法を選ぶことが大切です。
ここでは、5つの主要な方法を紹介します。
サンプルコードを交えながら、それぞれの特徴と使い方を詳しく解説していきますので、ぜひ集中して読み進めてくださいね。
きっと、DataRowの追加方法をマスターできるはずです。
○サンプルコード1:Addメソッドを使用
まずは、もっともシンプルな方法であるAddメソッドを使った方法から見ていきましょう。
Addメソッドは、新しいDataRowオブジェクトを作成し、DataTableに追加するための便利なメソッドです。
// DataTableの作成
DataTable dt = new DataTable();
// 列の定義
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
// Addメソッドを使ってDataRowを追加
dt.Rows.Add(1, "John", 25);
dt.Rows.Add(2, "Alice", 30);
dt.Rows.Add(3, "Bob", 35);
このコードでは、まずDataTableオブジェクトを作成し、列を定義しています。
そして、Addメソッドを使って、新しいDataRowを追加しています。
Addメソッドの引数には、各列の値を順番に指定します。
実行結果
ID Name Age
-- ---- ---
1 John 25
2 Alice 30
3 Bob 35
Addメソッドは、簡単にDataRowを追加できる反面、列の数が多い場合はコードが長くなる可能性があります。
また、列の順序を間違えると、意図しないデータが追加されてしまうので注意が必要です。
○サンプルコード2:ImportRowメソッドを利用
次に、ImportRowメソッドを使ったDataRowの追加方法を見ていきます。
ImportRowメソッドは、他のDataTableから行をコピーして追加するときに便利です。
// コピー元のDataTableを作成
DataTable sourceTable = new DataTable();
sourceTable.Columns.Add("ID", typeof(int));
sourceTable.Columns.Add("Name", typeof(string));
sourceTable.Columns.Add("Age", typeof(int));
sourceTable.Rows.Add(1, "John", 25);
// コピー先のDataTableを作成
DataTable destTable = new DataTable();
destTable.Columns.Add("ID", typeof(int));
destTable.Columns.Add("Name", typeof(string));
destTable.Columns.Add("Age", typeof(int));
// ImportRowメソッドを使って行をコピー
foreach (DataRow row in sourceTable.Rows)
{
destTable.ImportRow(row);
}
このコードでは、コピー元とコピー先の2つのDataTableを作成しています。
そして、foreach文を使ってコピー元のDataTableの行を1つずつ取り出し、ImportRowメソッドを使ってコピー先のDataTableに追加しています。
実行結果
コピー先のDataTable:
ID Name Age
-- ---- ---
1 John 25
ImportRowメソッドは、列の定義が同じDataTable間でデータをコピーするのに適しています。
ただし、列の定義が異なる場合は、エラーが発生するので注意が必要です。
○サンプルコード3:LoadDataRowメソッドを活用
LoadDataRowメソッドは、Object配列からDataRowを作成し、DataTableに追加するメソッドです。
列の順序を意識せずに、値の配列を渡すことができるので、コードの可読性が向上します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
// Object配列を作成
object[] rowValues1 = new object[] { 1, "John", 25 };
object[] rowValues2 = new object[] { 2, "Alice", 30 };
// LoadDataRowメソッドを使ってDataRowを追加
dt.LoadDataRow(rowValues1, true);
dt.LoadDataRow(rowValues2, true);
このコードでは、Object配列を使って行の値を定義しています。
そして、LoadDataRowメソッドを使って、その配列をDataRowに変換し、DataTableに追加しています。
実行結果
ID Name Age
-- ---- ---
1 John 25
2 Alice 30
LoadDataRowメソッドの第2引数は、行の追加方法を指定するためのものです。
trueを指定すると、新しい行が追加されます。falseを指定すると、既存の行が更新されます。
○サンプルコード4:NewRowメソッド後にAdd
NewRowメソッドを使うと、新しいDataRowオブジェクトを作成できます。
作成したDataRowオブジェクトのプロパティに値を設定し、最後にAddメソッドでDataTableに追加します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
// NewRowメソッドを使ってDataRowを作成
DataRow newRow1 = dt.NewRow();
newRow1["ID"] = 1;
newRow1["Name"] = "John";
newRow1["Age"] = 25;
DataRow newRow2 = dt.NewRow();
newRow2["ID"] = 2;
newRow2["Name"] = "Alice";
newRow2["Age"] = 30;
// DataTableにDataRowを追加
dt.Rows.Add(newRow1);
dt.Rows.Add(newRow2);
このコードでは、NewRowメソッドを使って新しいDataRowオブジェクトを作成しています。
そして、各列の値をプロパティに設定し、最後にAddメソッドでDataTableに追加しています。
実行結果
ID Name Age
-- ---- ---
1 John 25
2 Alice 30
NewRowメソッドを使う方法は、列の数が多い場合や、条件に応じて値を設定する必要がある場合に便利です。
ただし、コードが長くなる可能性があるので、可読性には注意が必要ですね。
○サンプルコード5:Mergeメソッドで複数行を一括追加
最後に、Mergeメソッドを使った方法を紹介します。
Mergeメソッドは、他のDataTableの行を一括して追加するためのメソッドです。
大量のデータを追加する場合に便利です。
// コピー元のDataTableを作成
DataTable sourceTable = new DataTable();
sourceTable.Columns.Add("ID", typeof(int));
sourceTable.Columns.Add("Name", typeof(string));
sourceTable.Columns.Add("Age", typeof(int));
sourceTable.Rows.Add(1, "John", 25);
sourceTable.Rows.Add(2, "Alice", 30);
sourceTable.Rows.Add(3, "Bob", 35);
// コピー先のDataTableを作成
DataTable destTable = new DataTable();
destTable.Columns.Add("ID", typeof(int));
destTable.Columns.Add("Name", typeof(string));
destTable.Columns.Add("Age", typeof(int));
// Mergeメソッドを使って行を一括追加
destTable.Merge(sourceTable);
このコードでは、コピー元とコピー先の2つのDataTableを作成しています。
そして、Mergeメソッドを使って、コピー元のDataTableの行を一括してコピー先のDataTableに追加しています。
実行結果
コピー先のDataTable:
ID Name Age
-- ---- ---
1 John 25
2 Alice 30
3 Bob 35
Mergeメソッドは、列の定義が同じDataTable間で大量のデータをコピーするのに適しています。
ただし、コピー先のDataTableに同じ主キーを持つ行が存在する場合は、エラーが発生するので注意が必要です。
●よくあるエラーとその対処法
DataRowをDataTableに追加する際、思わぬエラーに遭遇することがありますよね。
そんなときは、落ち着いて原因を特定し、適切な対処法を見つけることが大切です。
ここでは、よく発生するエラーとそのトラブルシューティング方法を紹介します。
エラーは、プログラミングの過程で避けられないものです。
しかし、エラーと上手に付き合うスキルを身につければ、開発の生産性が大幅に向上するはずです。
実際のコード例を交えながら、一緒にエラー対処のコツを学んでいきましょう。
きっと、C#でのデータ操作がより楽しくなるはずです。
○主要なエラー例とトラブルシューティング
最初に紹介するのは、”Index was out of range”エラーです。
このエラーは、DataRowの値を設定する際に、列のインデックスが範囲外であることを表しています。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
// DataRowの作成とエラーの発生
DataRow newRow = dt.NewRow();
newRow[0] = 1;
newRow[1] = "John";
newRow[2] = 25; // インデックスが範囲外
このコードでは、DataTableに”ID”と”Name”の2つの列を定義していますが、DataRowの3番目の列に値を設定しようとしているため、エラーが発生します。
エラーを解決するには、下記のように修正します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int)); // 列を追加
// DataRowの作成
DataRow newRow = dt.NewRow();
newRow[0] = 1;
newRow[1] = "John";
newRow[2] = 25; // エラーが解消
列を追加することで、インデックスが範囲内に収まり、エラーが解消されます。列のインデックスを間違えないよう、注意が必要ですね。
もう1つの代表的なエラーが、”Input array is longer than the number of columns in this table.”です。
このエラーは、LoadDataRowメソッドで渡す配列の要素数が、DataTableの列数より多い場合に発生します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
// Object配列の作成とエラーの発生
object[] rowValues = new object[] { 1, "John", 25 }; // 要素数が列数より多い
dt.LoadDataRow(rowValues, true);
このコードでは、DataTableに2つの列を定義していますが、LoadDataRowメソッドに渡す配列には3つの要素があるため、エラーが発生します。
エラーを解決するには、下記のように修正します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int)); // 列を追加
// Object配列の作成
object[] rowValues = new object[] { 1, "John", 25 }; // エラーが解消
dt.LoadDataRow(rowValues, true);
列の数と配列の要素数を一致させることで、エラーが解消されます。
LoadDataRowメソッドを使う際は、配列の要素数に注意しましょう。
○データ型の不一致による問題と解決策
DataRowの値を設定する際、データ型の不一致によるエラーが発生することがあります。
例えば、整数型の列に文字列型の値を設定しようとすると、エラーが発生します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
// DataRowの作成とエラーの発生
DataRow newRow = dt.NewRow();
newRow["ID"] = "1"; // 整数型の列に文字列型の値を設定
newRow["Name"] = "John";
dt.Rows.Add(newRow);
このコードでは、”ID”列は整数型ですが、文字列型の値 “1” を設定しようとしているため、エラーが発生します。
エラーを解決するには、下記のように修正します。
// DataTableの作成と列の定義
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
// DataRowの作成
DataRow newRow = dt.NewRow();
newRow["ID"] = 1; // 整数型の値を設定
newRow["Name"] = "John";
dt.Rows.Add(newRow);
列のデータ型に合わせて、適切な型の値を設定することで、エラーが解消されます。
列のデータ型を把握し、正しい型の値を設定するよう心がけましょう。
データ型の不一致は、ロジックエラーの原因にもなります。
例えば、整数型の列に小数点以下の値が設定されると、暗黙的な型変換が行われ、小数点以下が切り捨てられます。
このような暗黙的な型変換は、予期しない結果を引き起こすことがあるので注意が必要です。
●DataTableの応用例
DataTableは、単にデータを保持するだけでなく、様々な操作を行うことができます。
ここでは、DataTableの応用例として、フィルタリングやソート、データの集計、エクスポート、リレーショナルデータベースとの連携について見ていきましょう。
実際のコード例を通して、DataTableの応用方法を学ぶことで、C#でのデータ操作のスキルがさらに向上するはずです。
○サンプルコード6:フィルタリングとソート
DataTableには、データをフィルタリングしたり、ソートしたりする機能が備わっています。
この機能を使うことで、目的のデータを素早く見つけ出すことができます。
// サンプルデータを含むDataTableを作成
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Rows.Add(1, "John", 25);
dt.Rows.Add(2, "Alice", 30);
dt.Rows.Add(3, "Bob", 35);
dt.Rows.Add(4, "John", 40);
// フィルタリング
string filterExpression = "Name = 'John'";
DataRow[] filteredRows = dt.Select(filterExpression);
Console.WriteLine("フィルタリング結果:");
foreach (DataRow row in filteredRows)
{
Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}, Age: {row["Age"]}");
}
// ソート
dt.DefaultView.Sort = "Age DESC";
DataTable sortedTable = dt.DefaultView.ToTable();
Console.WriteLine("\nソート結果:");
foreach (DataRow row in sortedTable.Rows)
{
Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}, Age: {row["Age"]}");
}
実行結果
フィルタリング結果:
ID: 1, Name: John, Age: 25
ID: 4, Name: John, Age: 40
ソート結果:
ID: 4, Name: John, Age: 40
ID: 3, Name: Bob, Age: 35
ID: 2, Name: Alice, Age: 30
ID: 1, Name: John, Age: 25
このコードでは、まずサンプルデータを含むDataTableを作成しています。
そして、Selectメソッドを使ってデータをフィルタリングし、”Name”列の値が”John”である行を抽出しています。
次に、DefaultViewプロパティを使ってデータをソートしています。”Age”列を降順でソートし、その結果を新しいDataTableとして取得しています。
フィルタリングとソートは、データ分析や報告書の作成など、様々な場面で活用できる機能です。
条件式の指定方法を工夫することで、柔軟なデータ抽出が可能になります。
○サンプルコード7:データの集計
DataTableを使って、データの集計を行うこともできます。
ここでは、Computeメソッドを使った集計の例を紹介します。
// サンプルデータを含むDataTableを作成
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Columns.Add("Salary", typeof(decimal));
dt.Rows.Add(1, "John", 25, 5000);
dt.Rows.Add(2, "Alice", 30, 6000);
dt.Rows.Add(3, "Bob", 35, 7000);
dt.Rows.Add(4, "John", 40, 8000);
// 集計
int totalRows = (int)dt.Compute("COUNT(ID)", "");
int maxAge = (int)dt.Compute("MAX(Age)", "");
decimal avgSalary = (decimal)dt.Compute("AVG(Salary)", "");
Console.WriteLine($"総行数: {totalRows}");
Console.WriteLine($"最高年齢: {maxAge}");
Console.WriteLine($"平均給与: {avgSalary:C}");
実行結果
総行数: 4
最高年齢: 40
平均給与: ¥6,500.00
このコードでは、サンプルデータを含むDataTableを作成し、Computeメソッドを使ってデータを集計しています。
COUNT、MAX、AVGなどの集計関数を使って、総行数、最高年齢、平均給与を計算しています。
Computeメソッドの第1引数には集計式を指定し、第2引数にはフィルター式を指定します。
フィルター式を空文字列にすることで、全行を対象とした集計が行われます。
集計結果を表示する際は、適切な書式指定を行うことで、よりわかりやすい出力が得られます。
例えば、:C書式指定子を使うと、通貨形式で値が表示されます。
○サンプルコード8:データのエクスポート
DataTableのデータを他のアプリケーションで利用するために、エクスポートする方法を見ていきましょう。
ここでは、CSVファイルへのエクスポートを行います。
// サンプルデータを含むDataTableを作成
DataTable dt = new DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Rows.Add(1, "John", 25);
dt.Rows.Add(2, "Alice", 30);
dt.Rows.Add(3, "Bob", 35);
// CSVファイルにエクスポート
string csvFilePath = "data.csv";
string separator = ",";
// 列名の取得
string[] columnNames = dt.Columns.Cast<DataColumn>()
.Select(column => column.ColumnName)
.ToArray();
// 列名をCSVファイルに書き込む
File.WriteAllText(csvFilePath, string.Join(separator, columnNames) + Environment.NewLine);
// データ行をCSVファイルに追記
foreach (DataRow row in dt.Rows)
{
string[] fields = row.ItemArray.Select(field => field.ToString()).ToArray();
File.AppendAllText(csvFilePath, string.Join(separator, fields) + Environment.NewLine);
}
Console.WriteLine($"データを {csvFilePath} にエクスポートしました。");
実行結果
データを data.csv にエクスポートしました。
このコードでは、サンプルデータを含むDataTableを作成し、そのデータをCSVファイルにエクスポートしています。
まず、列名を取得するために、DataTableのColumnsプロパティからDataColumnオブジェクトを取得し、ColumnNameプロパティの値を配列に格納しています。
そして、列名をCSVファイルの1行目に書き込んでいます。
次に、データ行を1行ずつCSVファイルに追記しています。
DataRowオブジェクトのItemArrayプロパティを使って、各列の値を配列に取得し、string.Joinメソッドを使って、セパレーターで結合しています。
エクスポートが完了したら、メッセージを表示して、ファイルのパスを通知します。
○サンプルコード9:リレーショナルデータベースとの連携
DataTableは、リレーショナルデータベースとのデータのやり取りにも使用できます。
ここでは、SQL Serverとの連携を例に、データの読み込みと書き込みを行っています。
// データベース接続文字列
string connectionString = "Data Source=yourserver;Initial Catalog=yourdatabase;Integrated Security=True";
// SELECT文でデータを取得し、DataTableに読み込む
string selectQuery = "SELECT * FROM Users";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(selectQuery, connection);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable dt = new DataTable();
adapter.Fill(dt);
Console.WriteLine("Users テーブルのデータ:");
foreach (DataRow row in dt.Rows)
{
Console.WriteLine($"ID: {row["ID"]}, Name: {row["Name"]}, Age: {row["Age"]}");
}
}
// データをDataTableに追加し、INSERT文で書き込む
DataTable newData = new DataTable();
newData.Columns.Add("Name", typeof(string));
newData.Columns.Add("Age", typeof(int));
newData.Rows.Add("Mike", 40);
newData.Rows.Add("Emily", 35);
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("INSERT INTO Users (Name, Age) VALUES (@Name, @Age)", connection);
command.Parameters.Add("@Name", SqlDbType.NVarChar, 50, "Name");
command.Parameters.Add("@Age", SqlDbType.Int, 0, "Age");
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.InsertCommand = command;
adapter.Update(newData);
Console.WriteLine($"{newData.Rows.Count} 件のデータを追加しました。");
}
実行結果
Users テーブルのデータ:
ID: 1, Name: John, Age: 25
ID: 2, Name: Alice, Age: 30
ID: 3, Name: Bob, Age: 35
2 件のデータを追加しました。
このコードでは、SQL Serverとの連携を行うために、SqlConnectionオブジェクトを使用しています。
接続文字列には、サーバー名、データベース名、セキュリティ設定などを指定します。
SELECT文を使ってデータを取得する場合は、SqlDataAdapterオブジェクトを使用します。
SqlDataAdapterは、SELECT文の実行結果をDataTableに読み込むために使用されます。
Fill メソッドを呼び出すことで、クエリ結果がDataTableに格納されます。
INSERT文を使ってデータを書き込む場合も、SqlDataAdapterオブジェクトを使用します。
InsertCommandプロパティにINSERT文を設定し、パラメーターを追加します。
そして、Updateメソッドを呼び出すことで、DataTableのデータがデータベースに反映されます。
まとめ
C#とDataTableを使いこなすことで、効率的なデータ操作とアプリケーション開発が可能になります。
まずは、DataTableとDataRowの基本概念をしっかりと理解し、様々な方法でDataRowをDataTableに追加できるようになりましょう。
DataTableの応用的な使い方を学び、実践的なコード例を手がかりに開発に挑戦してみてください。
最後までお読みいただき、ありがとうございました。
本記事がC#とDataTableの理解に少しでも役立ったなら嬉しく思います。