C# 7.0はしばらく前にリリースされており、誰もが知っているように、新機能であるValueTupleにはタプルの最適化機能があります。 ここでは、ValueTupleの利点と使い方をよりよく理解するために、10分間でTupleとValueTupleの詳細な例を紹介します。
Tupleについて十分に知っているなら、「Review Tuple」セクションを飛ばして「ValueTuple Explained」セクションに直接行けば、価値タプルの素晴らしい使い方をご覧いただけます。
Tupleを振り返ってみろ
TupleはC# 4.0で新たに導入された機能で、.Net Framework 4.0以降で利用可能です。
タプルとは、特定の数と要素の列を持つデータ構造です。 例えば、学生情報を保存するトリプルデータ構造を設計します。これは合計3つの要素から成ります。1つ目は名前、2つ目は年齢、3つ目は身長です。
タプルの具体的な用途は以下の通りです:
1. タプルの作成方法
デフォルト。 ネットフレームワークタプルは1から7のタプル要素のみをサポートします8個以上の要素がある場合は、TupleのネストプロパティとRestプロパティを使って実装する必要があります。 さらに、タプルクラスはタプルオブジェクトを作成するための静的メソッドを提供します。
コンストラクタを使ってタプルを作成する:
最大8つの要素をサポートするタプル静的手法を用いてタプルを構築します:
注意:ここで構築されたタプル型は実際にはTuple<int, int, int, Tuple<int>>なので、testTuple8.Restで得られるデータ型はタプル<int>です。正確な値を得るにはItem1プロパティを取る必要があります。
2. データの集合を表す 下にタプルを作成し、生徒についての名前、年齢、身長の3つの情報を表現しますが、別々に追加クラスを作成する必要はありません。
3. メソッドから複数の値を返す 関数が複数の値を返す必要がある場合、一般的にアウトパラメータを用い、複数の値を返すためにアウトの代わりにタプルを使うことができます。
4. 単一パラメータ法におけるマルチバリュー転送
関数パラメータが1つのオブジェクトタイプのみの場合、タプル実装を用いて複数のパラメータ値を渡すことができます。
上記の便利な方法にもかかわらず、タプルには大きな欠点もあります:
- 要素にアクセスする際はItemX経由でしかアクセスできず、使用前に要素の順序を明確にしなければならず、属性名には実用的な意味がなく、覚えるのが不便です。
- 最大8つの元素があり、もっと欲しい場合は最後の元素でネストして拡張できます。
- タプルは参照型であり、他の単純型のような値型とは異なります。値型はヒープ上の領域を割り当て、CPU負荷が高いと作成や割り当て作業が多すぎることがあります。
そのため、C# 7.0で新しいValueTuple型が導入され、以下のセクションで詳述します。
ValueTupleが詳細に説明します
ValueTupleはC# 7.0の新機能の一つで、.Net Framework 4.7以上で利用可能です。
ValueTupleは4.7を必要としません。nugetで問題なければ4.7は内蔵されています。 さらに、ValueTupleは構造体タイプであり、Microsoftは64バイトを超える構造体の使用を推奨しており、これはValueTupleにも有効です。
値タプルは特定の数と要素列を表現するためのデータ構造でもありますが、タプルクラスとは異なり、以下のような主な違いがあります。
値タプルは構造体であり、値型でありクラスではありません。一方、タプルはクラス、参照型です。 値タプル要素は可変であり読み取り専用ではなく、値タプル内の要素の値を変更することができます。 データメンバーの値タプルはフィールドであり、属性ではありません。 値タプルの具体的な使い方は以下の通りです。
1. 値タプルの作成方法 タプルクラスと同様に、.Net Frameworkのバリュータプルは1から7個のタプル要素のみをサポートし、8つ以上の要素がある場合は、その価値タプルのネストプロパティとRestプロパティを使って実装する必要があります。 さらに、ValueTupleクラスは値タプルオブジェクトを作成するための静的メソッドも提供できます。
コンストラクタを使ってタプルを作成する:
最大8つの要素をサポートするタプル静的手法を用いてタプルを構築します:
ここで構築されたタプル型は実際にはTuple<int, int, <int>>なので、testTuple8.Restで得られるデータ型はTupleです<int>。正確な値を得るにはItem1プロパティを取る必要があります。
最適化の違い:7要素以上の値のタプルが構築された場合、そのネストされたタプルの値は以下のItemXでアクセスでき、上記の例ではtestTuple10.Rest.Item3またはtestTuple10.Item10を通じて10番目の要素にアクセスできます。
2. データの集合を表す 生徒についての名前、年齢、身長の3つの情報を表すための値のタプルを作成し、別々に追加クラスを作成せずに行います。
3. メソッドから複数の値を返す 値タプルは、関数定義のアウトパラメータの代わりに複数の値を返すこともあります。
最適化の違い:戻り値はValueTupleで不可解に指定でき、代わりに(string, int, uint)のような新しい構文(,例)を用います。
studentInfo型のデバッグはValueTypeトリプレットです。
最適化の違い:戻り値は、メモリ割り当てやアクセスの理解を容易にするために要素名を指定することができます:
便利なメモリ割り当て:
4. 単一パラメータ法におけるマルチバリュー転送 関数パラメータが1つのオブジェクト型のみの場合、値タプル実装を用いて複数の値を渡すことができます。
5. 値組の分解 タプル要素を解決してローカル変数を構成するにはvar (x, y) または (var x, var y) を使い、不要な要素は「_」記号で無視できます。
前述の通り、ValueTupleはC#をよりシンプルかつ使いやすくします。 Tupleに対する主な利点は以下の通りです:
- ValueTupleは関数のリターン値「(,,)」の新しい構文をサポートしており、コードがよりシンプルになりました。
- ここで注意すべきは、名前は付けられていますが、実際には値タプルはその名前の属性やフィールドを定義していません。実際の名前はItemXであり、すべての要素名は設計やコンパイル中のみ使用され、実行時には使われません(したがって、このタイプのシリアライズおよびデシリアライズ操作に注意してください)。
- 要素のタプルの一部またはすべてのものは、破壊手法を用いてより便利に使用できます。
- 値タプルは参照型のタプルよりも効率的な値型であり、値タプルには等しいかどうかを比較できる比較方法があります。詳細を参照してください:https://msdn.microsoft.com/en-us/library/system.valuetuple
|