using System;
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqAnyTutorial
{
// 学習用データモデル
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public int Price { get; set; }
public bool IsInStock { get; set; }
public List<string> Tags { get; set; } = new();
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("==============================================");
Console.WriteLine(" LINQ Any() 完全マスター講座 ");
Console.WriteLine("==============================================\n");
// テストデータの準備
var emptyList = new List<int>();
var numbers = new List<int> { 1, 3, 5, 8, 11 };
var products = new List<Product>
{
new Product { Id = 1, Name = "ノートPC", Price = 120000, IsInStock = true, Tags = new() { "家電", "PC" } },
new Product { Id = 2, Name = "マウス", Price = 2500, IsInStock = false, Tags = new() { "家電", "アクセサリ" } },
new Product { Id = 3, Name = "キーボード", Price = 8000, IsInStock = true, Tags = new() { "PC", "アクセサリ" } },
new Product { Id = 4, Name = "USBメモリ", Price = 1500, IsInStock = false, Tags = new() }
};
// ---------------------------------------------------------
// 1. 引数なし Any() : コレクションが空でないか確認する
// ---------------------------------------------------------
Console.WriteLine("--- 1. 引数なし Any() ---");
bool hasElements1 = emptyList.Any();
Console.WriteLine($"空のリストに要素はあるか?: {hasElements1}"); // False
bool hasElements2 = numbers.Any();
Console.WriteLine($"numbersに要素はあるか? : {hasElements2}"); // True
Console.WriteLine();
// ---------------------------------------------------------
// 2. 条件指定 Any(predicate) : 条件に合う要素が存在するか
// ---------------------------------------------------------
Console.WriteLine("--- 2. 条件指定 Any(predicate) ---");
// 偶数が1つでもあるか?
bool hasEvenNumber = numbers.Any(n => n % 2 == 0);
Console.WriteLine($"偶数は含まれるか? : {hasEvenNumber}"); // True (8が含まれる)
// 100以上のアドバンスな値があるか?
bool hasLargeNumber = numbers.Any(n => n >= 100);
Console.WriteLine($"100以上の値はあるか? : {hasLargeNumber}"); // False
Console.WriteLine();
// ---------------------------------------------------------
// 3. 実践編: オブジェクトのリストに対する条件判定
// ---------------------------------------------------------
Console.WriteLine("--- 3. 実践: 商品データの判定 ---");
// 在庫切れの商品が1つでも存在するか?
bool hasOutOfStock = products.Any(p => !p.IsInStock);
Console.WriteLine($"在庫切れ商品はあるか? : {hasOutOfStock}"); // True
// 200,000円を超える高額商品があるか?
bool hasExpensive = products.Any(p => p.Price > 200000);
Console.WriteLine($"20万超えの商品はあるか? : {hasExpensive}"); // False
Console.WriteLine();
// ---------------------------------------------------------
// 4. 応用編: 入れ子のコレクション(ネスト構造)の検索
// ---------------------------------------------------------
Console.WriteLine("--- 4. 応用: ネストしたリストの検索 ---");
// 「家電」タグが設定されている商品が存在するか?
bool hasAppliance = products.Any(p => p.Tags.Any(t => t == "家電"));
Console.WriteLine($"「家電」タグ付き商品はあるか?: {hasAppliance}"); // True
Console.WriteLine();
// ---------------------------------------------------------
// 5. 性能・パフォーマンス比較(Any vs Count)
// ---------------------------------------------------------
Console.WriteLine("--- 5. パフォーマンスの視点 (即時評価と遅延評価) ---");
// 判定用の述語関数(実行タイミング確認用)
bool IsEvenWithLog(int n)
{
Console.WriteLine($" [ログ] 要素 {n} を評価中...");
return n % 2 == 0;
}
Console.WriteLine("Any() の評価挙動(最初に条件を満たした時点で終了):");
// 8(3番目の要素)が偶数なので、11まで評価されずに即座に true を返して終了する(ショートサーキット)
bool resultAny = numbers.Any(IsEvenWithLog);
Console.WriteLine($"結果: {resultAny}\n");
// アンチパターン注意喚起:
// ✕ list.Count() > 0 や list.Where(...).Count() > 0
// 〇 list.Any() や list.Any(...)
Console.WriteLine("※解説: Count() > 0 は全要素を走査するため重くなりますが、");
Console.WriteLine(" Any() は1つ見つかった時点で処理を中断(ショートサーキット)するため高速です。");
Console.WriteLine("==============================================");
}
}
}