MeWrite Docs

InvalidOperationException

オブジェクトの現在の状態では無効な操作を実行した場合に発生するC#の例外

概要

System.InvalidOperationExceptionは、オブジェクトの現在の状態に対して無効なメソッド呼び出しを行った場合に発生します。LINQのSingle()First()で条件に一致する要素がない場合に特に頻繁に発生します。

エラーメッセージ

System.InvalidOperationException: Sequence contains no elements
   at System.Linq.ThrowHelper.ThrowNoElementsException()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
System.InvalidOperationException: Sequence contains no matching element
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)

原因

  1. 空のシーケンスにFirst()/Single()を使用: 要素が存在しないコレクションに対して呼び出し
  2. Single()で複数要素が該当: 一意であるべきクエリが複数の結果を返した
  3. 列挙中のコレクション変更: foreachループ内でコレクションを変更
  4. 無効な状態での操作: DbContextが破棄済み、Streamが閉じた後のアクセスなど

解決策

1. OrDefault系メソッドを使用する

要素が存在しない可能性がある場合はOrDefault付きメソッドを使う。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var users = new List<User>();

// NG: 要素がない場合にInvalidOperationException
var user = users.First();
var single = users.Single(u => u.Id == 999);

// OK: 要素がなければdefault(null)を返す
var user = users.FirstOrDefault();
var single = users.SingleOrDefault(u => u.Id == 999);

if (user is not null)
{
    Console.WriteLine(user.Name);
}

2. Any()で事前チェックする

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var orders = GetOrders(customerId);

// 事前に要素の存在を確認
if (orders.Any())
{
    var latest = orders.OrderByDescending(o => o.Date).First();
    Console.WriteLine($"最新注文: {latest.Id}");
}
else
{
    Console.WriteLine("注文はありません");
}

3. Try-パターンを実装する

操作が失敗する可能性がある場合、例外を投げずに結果を返す。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class UserService
{
    // Try-パターン: 成功/失敗をboolで返す
    public bool TryGetUser(int id, out User? user)
    {
        user = _context.Users.SingleOrDefault(u => u.Id == id);
        return user is not null;
    }

    // 使用側
    public void ProcessUser(int id)
    {
        if (_service.TryGetUser(id, out var user))
        {
            Console.WriteLine(user!.Name);
        }
        else
        {
            Console.WriteLine($"ユーザーID {id} が見つかりません");
        }
    }
}

4. 状態チェックを行う

操作前にオブジェクトの状態を確認する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// NG: DbContextが破棄済みの場合にInvalidOperationException
public class UserRepository
{
    private readonly AppDbContext _context;

    public async Task<User?> GetAsync(int id)
    {
        // usingスコープ外でアクセスするとエラー
        return await _context.Users.FindAsync(id);
    }
}

// OK: DIでライフサイクルを管理
public class UserRepository : IDisposable
{
    private readonly AppDbContext _context;
    private bool _disposed;

    public async Task<User?> GetAsync(int id)
    {
        ObjectDisposedException.ThrowIf(_disposed, this);
        return await _context.Users.FindAsync(id);
    }

    public void Dispose()
    {
        _disposed = true;
        _context.Dispose();
    }
}

5. Entity Frameworkでの対処

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// NG: 追跡中のエンティティを重複追加
var user = await _context.Users.FindAsync(1);
_context.Users.Add(user); // InvalidOperationException

// OK: 存在チェック後にAddOrUpdate
var existing = await _context.Users.FindAsync(1);
if (existing is null)
{
    _context.Users.Add(new User { Id = 1, Name = "Test" });
}
else
{
    existing.Name = "Updated";
}
await _context.SaveChangesAsync();

関連エラー

C# の他のエラー

最終更新: 2026-02-03