【C#】複数の変数をまとめて扱う(構造体/タプル/列挙型)

複数の変数、データ型をまとめて扱う際に、クラス以外にも取り扱う方法があるようなので、その特徴や使い方(使い分け)をまとめていきます。

構造体

構造体はクラスと似ていて、メンバ変数やメソッドを定義して複数の変数を取り扱うことができます。両社の違いとしては、構造体は値型、クラスは参照型となり、構造体はその型の値を直にほじすることができます。
基本的に構造体でできることはクラスでもできますが、構造体のメリットとしては、値を直接操作することができるため、読み書きが高速化できるなど、メモリ観点からの利点を持っています。

使い方

使い方としては以下のように、structで構造体であることを宣言し使用します。

//メンバ変数の定義
public struct     Grid{
    public int x;
    public int y;
    public int z;
}
//コンストラクタの定義
public Grid(int x, int y, int z){
    this.x = x;
    this.y = y;
    this.z = z;
}
//メソッドの定義
public int calcVolume(){
    return x * y * z;
}

注意点

構造体のメンバ変数は初期化子を使用することができず、コンストラクタで引数を渡す必要があります。引数なしのコンストラクタを定義することはできません。

また、構造体はインターフェースの実装なども可能ですが、継承などはできません。

用途

構造体はインスタンスのサイズが小さく、数値などのプリミティブ型(またはそれに類するもの)を扱う際に適しているようです。
インスタンスは16byte未満が推奨されており、16byte未満であれば参照型に比べ、メモリ効率がいいようです。

参考

【C#】構造体の使い方(クラスとの違い、初期化や配列の使用も解説)
構造体 - C# によるプログラミング入門 | ++C++; // 未確認 ... - ++C++
クラスと構造体の使い分け

タプル

タプルも複数の変数を扱うことができる複合型ですが、型名はつけません。タプルの主な用途としては、複数戻り値です。メソッドを定義する際の戻り値は通常、0個か1個ですが、タプルを利用することで複数の値を得ることができます。

使い方

//複数の型を持つ変数
private (int x, int y) value;
//foreachで要素を受け取る
foreach(var (s,n) in list){}

//Listなどの要素
var list = new List<(string s, int n)>();

//Dictionaryで複数のキー
var dic = new Dictionary<(int id, int subId),(string s, int n)>();

雑な例ですが、直感的に複数の型を扱いやすいかと思います。

用途

タプルは以下の場合に用いるといいようです。

・メンバー名だけで用途が想像がつく。良い型名がない。
・複数の戻り値がある場合。
・クラス内(privateな範囲)での使用。

気軽に用いることができる反面、型名などから得られる情報は少ないため、まずはクラスや構造体を検討し、タプルの乱用を防ぐ必要があります。

参考

C#7のタプルの使いどころ
タプル - C# によるプログラミング入門 | ++C++; // 未確認 ... - ++C++

列挙型

列挙型(enum)は、曜日など特定の値しかとらないデータを表現する際に用いる方です。switch-caseと相性がよく、セットで使われることが多くあります。

使い方

曜日を例にすると以下のように使います。

using System;

namespace Sample
{
 // enumの定義
 enum Days {
   Mon,
   Tue,
   Wed,
   Thu,
   Fri,
   Sat,
   Sun
 }
 
 class Sample
 {
   static void Main()
   {
     Days day = Days.Wed;
     
     switch(day) {
       case Days.Mon:
       case Days.Tue:
       case Days.Wed:
       case Days.Thu:
       case Days.Fri:
         Console.WriteLine("平日です");
         break;
       case Days.Sat:
       case Days.Sun:
         Console.WriteLine("休日です");
         break;
       default:
         Console.WriteLine("不正です");
         break;
     }
     
     Console.ReadKey();
   }
 }
}

enumのメンバー(列挙子)はint型ですが、別の型も指定することができるようです。

参考

【C#入門】enum(列挙型)の使い方総まとめ(文字列/int/foreach)

最後に

複数の変数を扱う方をまとめましたが、やはり使い分けが重要なようです。クラスと構造体、構造体とタプルはどちらを使うかのグレーゾーンは、考慮する要素もいくつかあり、広いように感じました。