こんにちは!FlutterやDartの開発現場で、日夜コードと格闘している先輩エンジニアです。
今日は、Dartの隠れた超重要機能である「コレクションリテラル内での条件付き要素挿入(Collection If)」について、その本質を徹底的に解説していきたいと思います。
他のプログラミング言語からDartに入ってきた方だと、「えっ、リストの中に直接 `if` が書けるの?」と驚かれることが多いんですよね。ここをクリアすれば、UIの構築もデータの加工も一気にスマートになり、Dartの基本はバッチリマスターできますよ!
それでは、なぜこの機能が素晴らしいのか、そして内部でどう動いているのかを一緒に見ていきましょう。
—
1. コレクション内 `if` の基本と、私たちがこれを使うべき理由
まずは、普通のリストの中に `if` を書く基本の形を見てみましょう。例えば、ユーザーの権限に応じてリストの要素を変えたいとき、こんなコードを書いたことはありませんか?
従来の手法(命令型のアプローチ)
void main() {
bool isAdmin = true;
// 一旦空のリストを作って、後からifで足していく
List
if (isAdmin) {
menu.add(‘管理者ダッシュボード’);
}
print(menu); // [ホーム, 設定, 管理者ダッシュボード]
}
これでも動きますが、リストが大きくなったり、UIを構築するコード(FlutterのWidgetツリーなど)になると、この書き方では「宣言的に書けない(コードを上から順に追って状態を脳内シミュレーションしないといけない)」という大きな欠点が生じます。
Dartのスマートな書き方(宣言的アプローチ)
Dartでは、コレクションリテラル(`[…]` や `{…}`)の中に、直接 `if` を埋め込むことができます。
void main() {
bool isAdmin = true;
// リストの中に直接ifを書く!
List
‘ホーム’,
‘設定’,
if (isAdmin) ‘管理者ダッシュボード’, // 条件が真の時だけここに要素が組み込まれる
];
print(menu); // [ホーム, 設定, 管理者ダッシュボード]
}
どうですか?まるで文章を書くように、自然にリストの構造が表現されていますよね。
—
2. 脳内イメージ:Dartがコレクションを構築する仕組み
「でもこれ、裏側ではどうやって動いているの? リストを作った後で要素をぶち込んでいるの?」という疑問を持つあなたは、エンジニアとして非常にセンスが良いです。
実は、DartのコンパイラとVMは、この構文を非常に効率的に処理しています。
イメージ図で考えてみましょう。コンパイル時、Dartはこれを「バラバラの要素を後から組み立てるコード」ではなく、「条件に応じてあらかじめ大きさが計算された配列を1回の命令で生成する(あるいはビルダーパターンを最適化した)コード」へとトランスパイル・評価します。
[ 評価のイメージ ]
List
‘ホーム’, 常に挿入 (Index: 0)
‘設定’, 常に挿入 (Index: 1)
if (isAdmin) <-- ここで真偽を判定!
'管理者ダッシュボード' trueなら (Index: 2) にスパッと配置、falseならそもそも領域を確保しない
];
命令型のように「一度空のリストを作って、後から `.add()` でメモリ領域を再割り当て(リサイズ)する」という無駄なオーバーヘッドが発生しません。コンパイルの段階でリストの構造が最適化されるため、実行時のパフォーマンスが非常に優れているのが特徴です。
—
3. 応用編:スプレッド演算子 (`…`) との組み合わせ
コレクション `if` が真価を発揮するのは、複数の要素をまとめて条件付きで挿入したいときです。ここでスプレッド演算子(`…`)が登場します。
void main() {
bool isAdvancedUser = true;
List
‘基本機能A’,
‘基本機能B’,
// 条件に一致した場合、複数の要素をごっそりリストに展開して挿入する
if (isAdvancedUser) …[
‘高度な機能X’,
‘高度な機能Y’,
],
];
print(features);
// 出力: [基本機能A, 基本機能B, 高度な機能X, 高度な機能Y]
}
もし `isAdvancedUser` が `false` であれば、`…[…]` の部分はまるごと無視され、余計なメモリや空のコレクションが生成されることもありません。この無駄のなさが、Dartの美しさです。
—
4. 陥りやすい罠:やってはいけない文法エラー
初学者の頃や、他の言語から移行したときによくやってしまうミスをいくつかご紹介します。ここを避けるだけで、エラーに悩まされる時間が劇的に減りますよ!
罠その1:セミコロン(`;`)を書いてしまう
つい文末の癖で `if (condition) ;` とセミコロンを入れたくなりますが、コレクション内ではセミコロンは厳禁です。
List
‘A’,
if (true) ‘B’; // ❌ エラー!コンパイルエラーになります
// if (true) ‘B’ と、式としてカンマで区切るのが正解
];
罠その2:通常の制御構文のつもりでブロック(`{}`)を書こうとする
Dartのコレクション `if` は「文(Statement)」ではなく「式(Expression)」の文脈で評価されます。そのため、通常の `if` のような波括弧 `{}` は使えません。
List
‘A’,
if (true) { // ❌ エラー!波括弧は使えません
‘B’,
‘C’,
}
// 正解:複数の要素を入れたいならスプレッド演算子を使う
if (true) …[‘B’, ‘C’],
];
—
まとめ
いかがでしたでしょうか?
- コレクション内 `if` は、命令型の手続きを宣言型にスマートに変換する機能
- 裏側では無駄なメモリ再割り当てを行わず、効率的にコレクションが構築される
- スプレッド演算子(`…`)と組み合わせることで、複数要素の条件付き挿入も自由自在
- セミコロンや波括弧 `{}` を書かないように注意する
このコレクション `if` は、純粋なDartのデータ処理だけでなく、FlutterでのUI構築(例えば「特定の権限がある時だけボタンを表示する」など)において、毎日のように使う必須のイディオムです。
ここをマスターしたあなたなら、より美しく、よりパフォーマンスの高いDartコードを書けるようになっているはずです。
ぜひ今日のコードをエディタで動かして、その軽快な挙動を体感してみてくださいね!それではまた次の記事でお会いしましょう。