0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

R02:【掟・判例】varの使い分け基準 迷いどころの明確化

Posted at

連載Index(読む順・公開済(リンク)はここが最新): S00_門前の誓い_総合Index

varは便利だ。宣言が短くなり、型名の重複も消える。
ただ、その便利さで「右辺を見ないと何の型か分からない宣言」が増えると、読む速度が落ちる。
問題はvarではなく、型と役割が宣言から消えてしまう書き方。
右辺で型が読めるか、型名が役割の説明になっているか。
この2点だけで使い分けの基準を揃える。

このページのゴール

  • varの正体(何が起きているか)を最短で掴む
  • 「右辺だけで型が分かる/分からない」を判断軸として明文化する
  • 「型名が役割を説明する」場面を判例として残す
  • LINQ/戻り値/数値リテラルの迷いどころを、表で明確化する
  • 指摘コメントがブレないレビュー基準へ落とす

先に切り分ける(似ているが別物)

  • varはコンパイル時に型が決まる
    実行時に挙動が変わる話ではなく、読みやすさ(情報の出し方)の話になる
  • dynamicは実行時解決になる
    静的チェックが効きにくく、議論の論点が別になる
  • varはローカル変数専用
    フィールド/プロパティ/引数の話へ広げると運用が壊れやすい

再発防止の掟: varの使い分け基準

  • 右辺だけで型が分かる場合のみvarを使う
    なぜ: 型探索の往復が消え、読み筋が切れにくくなるため
  • 右辺だけでは型が分からない場合、型名がその変数の役割を説明しているなら型を書く
    なぜ: 役割の説明が消えると誤読が増え、変更影響も追いにくくなるため
  • 戻り値varを採用する場合、変数名だけで用途が伝わることが前提になる
    なぜ: 型も用途も追えない状態が最も事故りやすいため
  • 型推論でも役割がその場で決まる形は許可する(out varなど)
    なぜ: 行内で型と用途が見え、読みが止まりにくくなるため

迷いどころを捌く順(最短)

  • 右辺だけで型が分かるか
  • 型名がその変数の役割を説明しているか
  • 変数名だけで用途が伝わるか
  • 1行に変換が詰まっていないか(LINQ/チェーン)

「右辺だけで型が分かる」の具体

右辺の形 判定 コメント
newで型名が出る new List<int>() 分かる varでノイズが減る
キャスト/型指定がある (Foo)x, Foo.Parse(s) 分かる 右辺に型名が居る
文字列リテラル "abc" 分かる 迷いが少ない
数値リテラル(サフィックスあり) 0m, 1.0d, 1.0f 分かる 意図が右辺に出る
数値リテラル(サフィックスなし) 0, 1 迷いが出る int/long/decimalなどの意図が消えることがある
メソッド戻り値 GetUser() 原則分からない 型名が右辺に居ない
LINQ/チェーン q.Where(...).Select(...) 分からない寄り 段数が増えるほど情報が潰れる
out var TryParse(..., out var n) 分かる寄り その行で型が決まるため読み筋が立つ

例: 使い分けの最小セット

// 右辺だけで型が分かる -> var
var list = new List<int>();
var sb = new StringBuilder();
var price = 0m; // 右辺でdecimalだと分かる

// 型名が役割を説明する -> 型を書く
UserId userId = GetUserId();
Money totalPrice = GetTotalPrice();

// out varは行内で型が決まる -> 許可
if (int.TryParse(text, out var n))
{
    // nはintとして読める
}

// 戻り値varは「変数名で用途が伝わる」時に成立しやすい
var activeCount = GetActiveCount();

判例(OK/NG)

観点 OK例 NG例 理由(事故) レビューで見る所
右辺だけで型が分かる(new) var list = new List<int>(); var list = CreateList(); 戻り値は型が隠れ、型探索が増える 右辺に型名が出ているか
型名が役割を説明する UserId userId = GetUserId(); var userId = GetUserId(); UserIdが見えないと「何のIDか」が揺れる 型名が役割説明になっているか
命名で用途が伝わる var count = users.Count; var data = GetData(); dataは用途が曖昧で、型も追いにくい 変数名が用途を表しているか
数値の型意図 decimal price = 0m; var price = 0; 金額なのにint扱いで桁/丸めの事故が起きる サフィックス(m/d/f)や型意図があるか
LINQの読み筋 var ids = users.Select(u => u.Id); var x = a.B().C().D().E(); 変換が詰まると意図も型も追えない 段数と分割ポイント
out var TryParse(s, out var n) outのみで後段が曖昧 後段で用途が揺れ、誤用が入りやすい その場で意味が見えているか

容赦なき断罪: レビュー観点

観点 ありがちな見落とし 事故の形 指摘コメント例(直球禁止)
右辺だけで分かるか 戻り値でもvarに寄せる 型探索が増え、変更影響も追いにくい 右辺だけでは型が見えにくいため、型を残す書き方の方が読み筋が立ちそう
型名が役割を説明するか UserId/Moneyなどをvarで隠す 役割が揺れて誤読が入る この型名は役割説明になっているため、ここは型を残す方が安全そう
命名で用途が伝わるか data/ret/tmpが混じる 用途も型も追えず、デバッグが詰む 変数名だけでは用途が伝わりにくいため、型か命名で分かる形に寄せたい
数値の意図が出ているか 0/1をvarで受ける int前提で桁/丸め/単位が崩れる 数値に型意図がありそうなので、型またはサフィックスで明確にした方が良さそう
チェーンの情報密度 1行に変換が密集 条件追加で崩れ、検証が難化 変換が多く意図が密集しているため、段階で名前を付ける構成が読みやすい
new()の扱い target-typed newを雑に混ぜる コンパイル不能/誤解を誘発 new()は左辺の型が前提になるため、ここは左辺で型を残す方が意図が伝わる

禁書庫A: 逆引き(症状→原因→対策)

症状 ありがちな原因 切り分け(見る場所) 最短の対処 再発防止(ルール化)
varを使うか迷って止まる 「右辺だけで分かる」の基準が無い 右辺に型名/サフィックスがあるか 右辺だけで分かるならvar、それ以外は次の判定へ 「右辺だけで分かる場合のみvar」を規約化
何を扱う変数か読めない 型名が役割説明なのにvarで隠れている 型名の語彙(UserId/Money等) 型を明示して役割を分かる形にする 「型名が役割説明なら型を書く」を運用化
var dataが増殖する 命名が用途を表していない 変数名の語彙 用途が分かる命名へ、または型で補う 曖昧語(data/ret/tmp)の抑制
LINQが読めない 変換が詰まり過ぎ チェーン段数 中間結果に名前を付けて分割 「チェーンは段階ごとに命名」
数値の型がズレる サフィックス無しリテラルをvarで受ける 0/1/1.0の形 型またはサフィックスで明示 金額/率/時間/単位は型で意図を残す

禁書庫B: チートシート(決め打ち)

  • var x = new Foo()は通る(右辺だけで分かる)
  • var x = GetFoo()は立ち止まる(右辺だけでは分からない)
  • UserId/Moneyなど型名が役割説明なら、varで隠さず型を書く
  • var price = 0mは通るが、var price = 0は型意図を疑う
  • チェーンが長い場合、型の議論より先に分割で読み筋を守る
  • var x = new();は成立しない(左辺の型が必要)

関連トピック

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?