InvalidOperationException は「今の状態ではその操作はできない」ときに出る。メッセージだけ見ると抽象的で、現場では LINQ・DI・コレクション周りでよく当たる。
この記事では、よくある発生パターンと対処の型をざっくり逆引きする。
Single / First の件数想定ミスが多い// 件数が想定外だと InvalidOperationException
var user = users.Single(u => u.Id == id);
Single: ちょうど1件必須。0件・複数件で例外SingleOrDefault: 0件は default。複数件は例外// 0件で InvalidOperationException
var user = users.First(u => u.Id == id);
// 0件は null(参照型)
var userOrNull = users.FirstOrDefault(u => u.Id == id);
複数件あっても先頭を取る。Single と違い「複数=異常」にはならない。
FirstOrDefault / SingleOrDefaultSingleforeach (var item in list)
{
if (item.IsExpired)
list.Remove(item); // InvalidOperationException
}
List<T> などを foreach 中に Add/Remove すると例外になる。
// 残すものを作り直す
list = list.Where(x => !x.IsExpired).ToList();
// または後ろから削除
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i].IsExpired)
list.RemoveAt(i);
}
var app = builder.Build();
builder.Services.AddSingleton<IMyService, MyService>(); // もう遅い
Build() 後のコンテナ変更は基本 NG。登録は Build() 前。
シングルトンから Scoped(例: DbContext)をコンストラクタ注入すると、実行時に InvalidOperation 系で怒られることがある。正しいスコープ(IServiceScopeFactory など)で取る。
GetRequiredService で未登録だと例外。Unable to resolve service for type ... も同系統。
IEnumerator.Current を MoveNext 前に読むInvalidOperationException = 状態と操作の不一致