メソッドの戻り値としてのタプル
outパラメーターを使わずに複数の結果を返します。
「メソッドの戻り値としてのタプル」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全4レッスンが含まれています。
複数の値を返す
メソッドが返せるものは1つだけですが、tuple を使えば、その1つの戻り値に複数の値をまとめられます。これは out パラメーターに代わる、すっきりした方法です。
using System;
class Program
{
static (int, int) Divide(int a, int b) => (a / b, a % b);
static void Main()
{
var result = Divide(17, 5);
Console.WriteLine(result.Item1 + " r " + result.Item2);
}
}名前付きタプルの戻り値の型
戻り値の要素に名前を付けると、メソッドの内容が分かりやすくなり、呼び出し側のコードも読みやすくなります。
using System;
class Program
{
static (int Quotient, int Remainder) Divide(int a, int b)
{
return (a / b, a % b);
}
static void Main()
{
var r = Divide(17, 5);
Console.WriteLine("Q=" + r.Quotient + ", R=" + r.Remainder);
}
}戻り値をデコンストラクトする
呼び出し側では、返されたタプルを個別の変数へ直接デコンストラクトできます。
using System;
class Program
{
static (double Min, double Max) Bounds(double[] data)
{
double min = data[0], max = data[0];
foreach (var d in data)
{
if (d < min) min = d;
if (d > max) max = d;
}
return (min, max);
}
static void Main()
{
var (lo, hi) = Bounds(new double[] { 3, 7, 1, 9, 4 });
Console.WriteLine("min=" + lo + ", max=" + hi);
}
}out パラメーターという選択肢
タプルが登場する前は、追加の値を返すために out パラメーターを使っていました。現在も使用できますが、宣言や呼び出しがやや煩雑です。
using System;
class Program
{
static int Divide(int a, int b, out int remainder)
{
remainder = a % b;
return a / b;
}
static void Main()
{
int rem;
int q = Divide(17, 5, out rem);
Console.WriteLine("Q=" + q + ", R=" + rem);
}
}タプルと out: 読みやすさ
タプルによる戻り値では、すべての結果を戻り値にまとめられ、デコンストラクションによって自然に読み取れます。そのため、単純なケースでは通常 out よりも好まれます。
using System;
class Program
{
static (int Sum, int Count) Stats(int[] nums)
{
int sum = 0;
foreach (var n in nums) sum += n;
return (sum, nums.Length);
}
static void Main()
{
var (sum, count) = Stats(new[] { 2, 4, 6 });
Console.WriteLine("Sum=" + sum + ", Count=" + count);
}
}ステータスと値を返す
よくあるパターンは、結果とともに成功フラグを返す方法です。Try パターンに似ていますが、1つのタプルにまとめられています。
using System;
class Program
{
static (bool Ok, int Value) ParseAge(string s)
{
if (int.TryParse(s, out int n) && n >= 0)
return (true, n);
return (false, 0);
}
static void Main()
{
var r = ParseAge("42");
Console.WriteLine(r.Ok ? "Parsed " + r.Value : "Invalid");
}
}out が今でも役立つ場合
組み込みの Try パターン(int.TryParse)では、out が今でも自然な書き方です。ブール値の結果と1つの out 値を返す形式が慣例になっています。
using System;
class Program
{
static void Main()
{
if (int.TryParse("100", out int value))
Console.WriteLine("Got " + value);
else
Console.WriteLine("Not a number");
}
}複数の名前付きフィールドを返す
タプルを使えば、その場限りのクラスを作成せずに複数の結果へ対応できます。
using System;
class Program
{
static (int Min, int Max, double Avg) Analyze(int[] nums)
{
int min = nums[0], max = nums[0], sum = 0;
foreach (var n in nums)
{
if (n < min) min = n;
if (n > max) max = n;
sum += n;
}
return (min, max, (double)sum / nums.Length);
}
static void Main()
{
var a = Analyze(new[] { 4, 8, 2, 6 });
Console.WriteLine("min=" + a.Min + ", max=" + a.Max + ", avg=" + a.Avg);
}
}クラスを優先する場合
まとめたデータに動作がある場合、広く再利用する場合、または検証が必要な場合は、どこでもタプルを返すのではなく、クラスや record を定義しましょう。
using System;
class Program
{
// Fine as a tuple: small, local, no behavior
static (int W, int H) ParseSize(string s)
{
var parts = s.Split('x');
return (int.Parse(parts[0]), int.Parse(parts[1]));
}
static void Main()
{
var (w, h) = ParseSize("16x9");
Console.WriteLine(w + " by " + h);
}
}返されたタプルを連結する
返されたタプルをインラインでデコンストラクトし、そのまま別の計算に渡すことができます。
using System;
class Program
{
static (int, int) Split(int total) => (total / 2, total - total / 2);
static void Main()
{
var (a, b) = Split(7);
Console.WriteLine("Halves: " + a + " + " + b + " = " + (a + b));
}
}まとめ
名前付きタプルを返すことは、余計な定型コードを増やさずに、関連する少数の値をメソッドから返すための、現代的で読みやすい方法です。
using System;
class Program
{
static (bool Found, int Index) Search(int[] arr, int target)
{
for (int i = 0; i < arr.Length; i++)
if (arr[i] == target) return (true, i);
return (false, -1);
}
static void Main()
{
var r = Search(new[] { 5, 8, 12 }, 8);
Console.WriteLine(r.Found ? "At index " + r.Index : "Not found");
}
}理解度チェック
タプルの戻り値について理解できているか確認しましょう。
まとめ
tuple を返すと、メソッドから複数の値を一度に返せます。多くの場合、out よりもすっきりした選択肢です。分かりやすさのために要素へ名前を付け、呼び出し側でデコンストラクトしましょう。慣例的な Try パターンには out を使い、データに動作がある場合や広く再利用する場合は、クラスや record を優先します。
using System;
class Program
{
static (int Sum, int Max) Go(int[] n)
{
int s = 0, m = n[0];
foreach (var x in n) { s += x; if (x > m) m = x; }
return (s, m);
}
static void Main()
{
var (sum, max) = Go(new[] { 3, 9, 5 });
Console.WriteLine(sum + " / " + max);
}
}よくある質問
「メソッドの戻り値としてのタプル」レッスンは無料ですか?
はい。「メソッドの戻り値としてのタプル」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全4レッスンが含まれています。
「メソッドの戻り値としてのタプル」で何を学びますか?
outパラメーターを使わずに複数の結果を返します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「メソッドの戻り値としてのタプル」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。