フッターコンテンツにスキップ
Iron Academy Logo
C#を学ぶ
C#を学ぶ

その他のカテゴリー

10分以内で学ぶ C# のタプル入門

[[academy-video-youtube({"vid": "QC6hpl2iU0c", "start_time": "0", "title": "Intro to Tuples in C# In 10 Minutes or Less", "creator": "Tim Corey", "length": "9m 49s"})]]

C#メソッドは、単一の戻り値を中心に設計されていますが、1つの戻り値が本当に十分でない場合があります。 住所の検証はクラシックな例です: 入力が有効かどうかを知りたくなり、もし有効であれば、きれいに整形された正規の形式を返したいです。 そのペアを新しいクラスにラップするのは1つのメソッドにしては重く、outパラメーターは入力と出力を悪化させる混乱を招く。 タプルは、正確にこの状況に対してよりクリーンな回答をもらたすために言語に追加されました。

彼のビデオ "Intro to Tuples in C# In 10 Minutes or Less" で、Tim Coreyはタプルを使って、フォーマットされた文字列と有効性フラグの両方を返す必要がある小さな住所検証メソッドを構築しています。 彼は途中でタプルを返すための構文、メンバーに名前を付けることがなぜ重要か、呼び出し元で結果を別々の変数に分割する方法、および捨てる文字によって気にしない部分をスキップする方法について説明します。 単発の結果クラスやoutパラメータに頼る読者は、ここで軽量なパターンを見つけるでしょう。

問題: 複数の値の返却

[0:18 - 2:50] Timはストリート住所文字列を受け取るValidateAddressメソッドで開始します。 彼が望む動作は単純です: 入力が"123 Sesame St"に一致した場合、適切にフォーマットされた"123 Sesame Street"を返します。 そうでない場合は、その住所が無効であることを示します。 1回の呼び出しから戻る必要がある情報は、整形済みの文字列と成功フラグの2つです。

タプル前のオプションはどちらも不格好です。 ValidateAddressResultクラスを作成することは機能しますが、他のコードがインスタンス化しない一目的の型をプロジェクトに残すことになります。 フォーマットされた住所をパラメータリストを通して送り返すために、出力パラメータを使用することも機能しますが、入力と出力をメソッドシグネチャで混在させ、呼び出し元を読みづらくします。 タプルは、これらのコストを払わずにこのケースを処理するために導入されました。

名前なしのタプルを返す

[2:50 - 4:01] タプルの戻り値型の最小構文は、2つの型を丸括弧で囲みます。

public (string, bool) ValidateAddress(string address)
{
    if (address == "123 Sesame St")
    {
        return ("123 Sesame Street", true);
    }
    return (address, false);
}
public (string, bool) ValidateAddress(string address)
{
    if (address == "123 Sesame St")
    {
        return ("123 Sesame Street", true);
    }
    return (address, false);
}

メソッドは現在(string, bool)ペアを返します。 何かがそれを使用しようとしたとき、すぐに欠点が現れます。 メンバーに名前が割り当てられていないため、IntelliSenseはそれらをItem2として公開し、それぞれの値が何を表しているかについて次の読者には何も伝えません。 Timは、構文が最も短いにもかかわらず、無名のタプルを出荷しない理由としてこれを指摘します。6か月後にresult.Item2を読むコストは、一度名前を入力するコストよりも高いです。

タプルメンバーの名前付け

[4:01 - 6:30] タプルの各メンバーに名前を割り当てるには、戻り値型宣言を一行で変更します。

public (string Address, bool IsValid) ValidateAddress(string address)
{
    if (address == "123 Sesame St")
    {
        return ("123 Sesame Street", true);
    }
    return (address, false);
}
public (string Address, bool IsValid) ValidateAddress(string address)
{
    if (address == "123 Sesame St")
    {
        return ("123 Sesame Street", true);
    }
    return (address, false);
}

今、呼び出しサイトは自然に読み取れます。

var result = ValidateAddress("123 Sesame St");

if (result.IsValid)
{
    Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
    Console.WriteLine("That is an invalid address");
}
var result = ValidateAddress("123 Sesame St");

if (result.IsValid)
{
    Console.WriteLine($"Your validated address is {result.Address}");
}
else
{
    Console.WriteLine("That is an invalid address");
}

"123 Sesame St" でコードを実行すると、標準形式が印刷されます。 先頭の1を取り除いて"23 Sesame St"を生成することで、IsValidがfalseとして返され、無効なアドレスのメッセージが表示されます。 メソッドの契約は、サポートクラスファイルを必要としない名前付きタプルなしで、呼び出しサイトで自己文書化されるようになりました。

タプルは2つ以上のメンバーを含むことができます。 3つ、4つ、または5つも同様に動作します。 ティムは、タプルが3つか4つ以上のメンバーを持つようになると、レコードやクラスが通常より明確な選択肢になると述べていますが、1つのメソッドからの2つまたは3つの関連する値の場合、タプルは軽量なオプションのままです。

別々の変数にタプルをデコンストラクトする

[6:30 - 7:39] 呼び出し元が単一のresultにドットを打つ代わりに、結果の各部分を独自の変数で保持したいと思うこともあります。 C# はデコンストラクション構文を直接サポートしています。

(string message, bool valid) = ValidateAddress("123 Sesame St");

if (valid)
{
    Console.WriteLine($"Your validated address is {message}");
}
(string message, bool valid) = ValidateAddress("123 Sesame St");

if (valid)
{
    Console.WriteLine($"Your validated address is {message}");
}

左側の変数名は、メソッド上のタプルメンバー名と一致する必要はありません。 ここでは、IsValidに置き換わります。 ティムは、これが デコンストラクタ であり、デストラクタではないと指摘します。 2つの単語は似ていますが、まったく異なる概念を指します。デコンストラクタは、タプルを呼び出し側が実際に望むローカル変数に分割します。

ディスカード文字で値をスキップする

[7:41 - 8:54] 呼び出し元が返された値のサブセットのみに関心がある場合、無視文字(_)は不要なものを捨てます:

(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);
(string message, _) = ValidateAddress("123 Sesame St");
Console.WriteLine(message);

アンダースコアはコンパイラに"この値を意図的に無視している"と伝えます。これは、不要なメンバーを未使用のような捨て変数名に割り当てるよりも表現力があります。ディスカードは意図を伝えるからです。 行を読む誰もが、IsValidを無視することがこの呼び出しサイトでは意図的な選択であり、見落としではないと知っています。

結論: タプルがその場所に値する時

[8:54 - 9:28] タプルの主なユースケースは、一度しか返されないクラスを作成せずに、メソッドから複数の値を返すことです。 メソッド署名でメンバーに名前を付け、呼び出しサイトでデコンストラクトし、呼び出し側が必要としないものをディスカードすることが、タプルを快適に扱うための3つのパターンです。 それを超えて、タプルは LINQ プロジェクションと中間計算で有用であり、匿名型よりも読みやすい迅速なペアドバリューを提供します。

結論

[9:28 - 9:49] タプルは、C# にメソッドから複数の値を返すコンパクトな方法を提供します。 名前付きの形式は日々使用する価値のあるバージョンであり、result.Item1は読み取りません。 呼び出し側がその形を好む場合、デコンストラクションが部分をローカル変数に戻し、ディスカード文字は単一の呼び出しで必要なものだけを取得させます。

例ヒント: 3つ以上の場所で同じタプル形状をデコンストラクトし始めたとき、それがレコードに昇格する信号です。 タプルは1つのメソッドにローカルな形で輝きます。 その形があなたのドメインの一部となった瞬間、名前付き型はそれ自体に値します。

YouTube チャンネルで完全なビデオを視聴し、現代的で表現力豊かな C# の書き方についてのさらなる洞察を得てください。

Hero Worlddot related to 10分以内で学ぶ C# のタプル入門
Hero Affiliate related to 10分以内で学ぶ C# のタプル入門

好きなことを共有することで収入を増やす

.NET、C#、Java、Python、またはNode.jsを使用する開発者向けのコンテンツを作成しますか?あなたの専門知識を副収入に変えましょう!

アイアンサポートチーム

私たちは週5日、24時間オンラインで対応しています。
チャット
メール
電話してね