bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [C#] メソッドパラメータの修飾子 — out / ref / in / params

[C#] メソッドパラメータの修飾子 — out / ref / in / params

Apr 10, 2026 C# , .NET bucket-sort

C# のメソッド引数は、修飾子なしでは値のコピーが渡される(値渡し)のが基本です。out・ref・in・params の 4 つの修飾子を使うと、それぞれ異なる渡し方ができます。

修飾子なし(値渡し)

修飾子がない場合、呼び出し元の変数のコピーがメソッドに渡されます。メソッド内で値を変更しても、呼び出し元の変数には影響しません。

void Double(int x)
{
    x = x * 2; // コピーを変更
}

int value = 5;
Double(value);
Console.WriteLine(value); // 5(変わらない)

ref — 参照渡し

ref を使うと、変数の**参照(アドレス)**がメソッドに渡されます。メソッド内での変更が呼び出し元の変数に反映されます。

void Double(ref int x)
{
    x = x * 2; // 呼び出し元の変数を変更
}

int value = 5;
Double(ref value);
Console.WriteLine(value); // 10

ref のルール

  • 呼び出し元でも ref を明示する必要があります(Double(ref value))
  • 渡す変数は事前に初期化されていなければなりません
  • 変数(var・フィールド・配列の要素など)しか渡せません(リテラルや式は不可)

主な用途

複数の値を返したいが構造体やタプルにまとめたくない場合、または大きな構造体をコピーなしに書き換えたい場合に使います。

void Swap(ref int a, ref int b) => (a, b) = (b, a);

int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 2, 1

out — 出力パラメータ

out は ref と似ていますが、メソッド内で必ず値を代入しなければならないという制約があります。呼び出し元では初期化せずに渡せます。

bool TryParse(string input, out int result)
{
    if (int.TryParse(input, out int value))
    {
        result = value;
        return true;
    }
    result = 0; // 必ず代入が必要
    return false;
}

if (TryParse("42", out int number))
{
    Console.WriteLine(number); // 42
}

out のルール

  • 呼び出し元でも out を明示する(TryParse("42", out int number))
  • 呼び出し元で変数を事前初期化しなくてよい
  • メソッド内ですべてのコードパスで値を代入しないとコンパイルエラー

インライン宣言(C# 7.0)

C# 7.0 から out の宣言を呼び出し箇所でインライン記述できるようになりました。

// 事前に変数を宣言しなくてよい
if (int.TryParse("123", out int value))
{
    Console.WriteLine(value);
}

ref と out の違い

ref out
呼び出し元での初期化 必要 不要
メソッド内での代入 任意 必須
主な用途 読み書き両方 出力専用

in — 読み取り専用参照渡し(C# 7.2)

in は C# 7.2 で追加された修飾子です。ref と同様に参照を渡しますが、メソッド内で値を変更できない(読み取り専用)という制約があります。

void PrintPoint(in Point p)
{
    Console.WriteLine($"({p.X}, {p.Y})");
    // p.X = 0; // コンパイルエラー(変更不可)
}

var point = new Point(3, 4);
PrintPoint(in point);
// または修飾子なしで呼び出すことも可能
PrintPoint(point);

in のルール

  • 呼び出し元で in を明示する(省略も可能)
  • 渡す変数は事前に初期化されていなければならない
  • メソッド内で値を変更するとコンパイルエラー

in の主な用途

大きな struct をコピーなしに渡しつつ、変更されないことを保証したい場合に有効です。

readonly struct Matrix4x4
{
    // 4x4 行列(64 バイト)
}

// コピーを発生させずに参照渡し、かつ変更を禁止
double Determinant(in Matrix4x4 m) { /* ... */ }

小さな型(int・double など)では参照の管理コストがコピーコストを上回ることもあるため、大きな struct への適用が主な使い所です。

params — 可変長引数

params を使うと、呼び出し元で任意の個数の引数を列挙して渡せます。メソッド内では配列として受け取ります。

int Sum(params int[] numbers)
{
    return numbers.Sum();
}

Console.WriteLine(Sum(1, 2, 3));       // 6
Console.WriteLine(Sum(10, 20));        // 30
Console.WriteLine(Sum());              // 0(空の配列)
Console.WriteLine(Sum(new[] { 1, 2 })); // 配列を直接渡すことも可能

params のルール

  • params はパラメータリストの最後の 1 つだけに付けられます
  • params パラメータの型は配列型でなければなりません(C# 12 以前)
  • 呼び出し側で配列を直接渡すことも、個別に列挙することも両方できます

他のパラメータとの組み合わせ

string Format(string separator, params string[] values)
    => string.Join(separator, values);

Console.WriteLine(Format(", ", "A", "B", "C")); // A, B, C

C# 13 の params の拡張

C# 13 で params が配列以外のコレクション型にも対応しました。

// C# 13 以降:Span<T> も使用可能
int Sum(params ReadOnlySpan<int> numbers)
{
    int total = 0;
    foreach (var n in numbers) total += n;
    return total;
}

params ReadOnlySpan<T> を使うとヒープ割り当てを避けられ、パフォーマンスが改善します。

まとめ

修飾子 参照渡し 呼び出し元での初期化 メソッド内での変更 主な用途
なし ✗(値渡し) 不要 不可(呼び出し元に影響なし) 通常の引数
ref ✓ 必要 可 読み書き両用の参照渡し
out ✓ 不要 必須(必ず代入) 複数の戻り値・Try パターン
in ✓ 必要 不可(読み取り専用) 大きな struct の効率的な受け渡し
params ✗(値渡し) — 可 可変長引数
C# .NET Out Ref In Params
← [C#] Expression-Bodied メンバ・ローカル関数・static ローカル関数 [C#] Named Arguments(名前付き引数) →

Related Posts

  • [C#] Disposable Objects — IDisposable / Dispose() と using 構文 May 12, 2026
  • [C#] Finalizable Objects — Finalize() の役割と使いどころ May 11, 2026
  • [C#] System.GC クラスを整理する — ガベージコレクションを制御するための API May 10, 2026
  • [C#] IComparable と IComparer — オブジェクトの順序比較と複数ソート戦略 May 9, 2026

Table of Contents

  • 修飾子なし(値渡し)
  • ref — 参照渡し
    • ref のルール
    • 主な用途
  • out — 出力パラメータ
    • out のルール
    • インライン宣言(C# 7.0)
    • ref と out の違い
  • in — 読み取り専用参照渡し(C# 7.2)
    • in のルール
    • in の主な用途
  • params — 可変長引数
    • params のルール
    • 他のパラメータとの組み合わせ
    • C# 13 の params の拡張
  • まとめ

Recent Posts

  • [C#] Disposable Objects — IDisposable / Dispose() と using 構文 May 12, 2026
  • [C#] Finalizable Objects — Finalize() の役割と使いどころ May 11, 2026
  • [C#] System.GC クラスを整理する — ガベージコレクションを制御するための API May 10, 2026
  • [C#] IComparable と IComparer — オブジェクトの順序比較と複数ソート戦略 May 9, 2026
  • [C#] ICloneable インターフェース — オブジェクトのコピーと浅いコピー・深いコピー May 8, 2026

Categories

  • C#62
  • .NET61
  • AWS27
  • Laravel16
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Filament1
  • Git1
  • SQS1

Tags

  • C#
  • .NET
  • AWS
  • Laravel
  • PHP
  • セキュリティ
  • MySQL
  • Linux
  • Apache
  • Code Snippet
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • パフォーマンス
  • DoS
  • Nginx
  • Windows
  • WordPress
  • メモリ管理
  • 監視
  • 設計
  • Amazon Linux 2023
  • Docker
  • Ipset
  • Iptables
  • OPCache
  • Webサーバー
  • オブジェクト指向
  • クラス設計
  • コレクション
  • パターンマッチング
  • 継承
  • 認可
  • Aurora
  • Blade
  • Grafana
  • Hugo
  • IDisposable
  • InfluxDB
  • Policy
  • Record
  • SSG
  • インターフェース
  • エラーハンドリング
  • カプセル化
  • ガベージコレクション
  • デザインパターン
  • モニタリング
  • 例外
Powered by Hugo & Explore Theme.