[{"data":1,"prerenderedAt":4006},["ShallowReactive",2],{"navigation_docs":3,"-phong-van-lo-trinh-ngay-3-csharp-nang-cao":420,"-phong-van-lo-trinh-ngay-3-csharp-nang-cao-surround":4001},[4,153],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":26},"Phỏng vấn .NET","i-lucide-briefcase","\u002Fphong-van","1.phong-van",[10,27,66,111,128],{"title":11,"icon":12,"path":13,"stem":14,"children":15,"page":26},"Tổng quan","i-lucide-compass","\u002Fphong-van\u002Ftong-quan","1.phong-van\u002F1.tong-quan",[16,21],{"title":17,"path":18,"stem":19,"icon":20},"Thị trường HCM","\u002Fphong-van\u002Ftong-quan\u002Fthi-truong","1.phong-van\u002F1.tong-quan\u002F1.thi-truong","i-lucide-trending-up",{"title":22,"path":23,"stem":24,"icon":25},"Lộ trình 7 ngày","\u002Fphong-van\u002Ftong-quan\u002Flo-trinh","1.phong-van\u002F1.tong-quan\u002F2.lo-trinh","i-lucide-calendar-days",false,{"title":22,"icon":25,"path":28,"stem":29,"children":30,"page":26},"\u002Fphong-van\u002Flo-trinh","1.phong-van\u002F2.lo-trinh",[31,36,41,46,51,56,61],{"title":32,"path":33,"stem":34,"icon":35},"Ngày 1 — C# cơ bản","\u002Fphong-van\u002Flo-trinh\u002Fngay-1-csharp-co-ban","1.phong-van\u002F2.lo-trinh\u002F1.ngay-1-csharp-co-ban","i-lucide-1",{"title":37,"path":38,"stem":39,"icon":40},"Ngày 2 — OOP và SOLID","\u002Fphong-van\u002Flo-trinh\u002Fngay-2-oop-solid","1.phong-van\u002F2.lo-trinh\u002F2.ngay-2-oop-solid","i-lucide-2",{"title":42,"path":43,"stem":44,"icon":45},"Ngày 3 — C# nâng cao","\u002Fphong-van\u002Flo-trinh\u002Fngay-3-csharp-nang-cao","1.phong-van\u002F2.lo-trinh\u002F3.ngay-3-csharp-nang-cao","i-lucide-3",{"title":47,"path":48,"stem":49,"icon":50},"Ngày 4 — Database và SQL","\u002Fphong-van\u002Flo-trinh\u002Fngay-4-database-sql","1.phong-van\u002F2.lo-trinh\u002F4.ngay-4-database-sql","i-lucide-4",{"title":52,"path":53,"stem":54,"icon":55},"Ngày 5 — ASP.NET Core và EF Core","\u002Fphong-van\u002Flo-trinh\u002Fngay-5-aspnet-efcore","1.phong-van\u002F2.lo-trinh\u002F5.ngay-5-aspnet-efcore","i-lucide-5",{"title":57,"path":58,"stem":59,"icon":60},"Ngày 6 — DSA coding","\u002Fphong-van\u002Flo-trinh\u002Fngay-6-dsa","1.phong-van\u002F2.lo-trinh\u002F6.ngay-6-dsa","i-lucide-6",{"title":62,"path":63,"stem":64,"icon":65},"Ngày 7 — Mock và HR","\u002Fphong-van\u002Flo-trinh\u002Fngay-7-mock-interview","1.phong-van\u002F2.lo-trinh\u002F7.ngay-7-mock-interview","i-lucide-7",{"title":67,"icon":68,"path":69,"stem":70,"children":71,"page":26},"Ngân hàng câu hỏi","i-lucide-database","\u002Fphong-van\u002Fngan-hang-cau-hoi","1.phong-van\u002F3.ngan-hang-cau-hoi",[72,77,82,87,92,97,102,107],{"title":73,"path":74,"stem":75,"icon":76},"C# (60+ câu)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fcsharp","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F1.csharp","i-lucide-hash",{"title":78,"path":79,"stem":80,"icon":81},"OOP và SOLID (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Foop","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F2.oop","i-lucide-shapes",{"title":83,"path":84,"stem":85,"icon":86},"SQL (40+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fsql","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F3.sql","i-lucide-database-zap",{"title":88,"path":89,"stem":90,"icon":91},"ASP.NET và EF (50+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-ef","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F4.aspnet-ef","i-lucide-server",{"title":93,"path":94,"stem":95,"icon":96},"DSA và Coding (30+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdsa-coding","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F5.dsa-coding","i-lucide-binary",{"title":98,"path":99,"stem":100,"icon":101},"HR và Soft skill (25+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fhr-behavior","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F6.hr-behavior","i-lucide-users",{"title":103,"path":104,"stem":105,"icon":106},"Design Pattern (55+)","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Fdesign-pattern","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F7.design-pattern","i-lucide-puzzle",{"title":108,"path":109,"stem":110,"icon":91},"ASP.NET MVC và Web API","\u002Fphong-van\u002Fngan-hang-cau-hoi\u002Faspnet-mvc-webapi","1.phong-van\u002F3.ngan-hang-cau-hoi\u002F8.aspnet-mvc-webapi",{"title":112,"itle":113,"icon":114,"path":115,"stem":116,"children":117,"page":26},"Tai Lieu","Tài liệu và Cheat sheet","i-lucide-book-marked","\u002Fphong-van\u002Ftai-lieu","1.phong-van\u002F4.tai-lieu",[118,123],{"title":119,"path":120,"stem":121,"icon":122},"Cheat Sheet","\u002Fphong-van\u002Ftai-lieu\u002Fcheatsheet","1.phong-van\u002F4.tai-lieu\u002F1.cheatsheet","i-lucide-clipboard-list",{"title":124,"path":125,"stem":126,"icon":127},"Nguồn tham khảo","\u002Fphong-van\u002Ftai-lieu\u002Fnguon","1.phong-van\u002F4.tai-lieu\u002F2.nguon","i-lucide-link",{"title":129,"icon":130,"path":131,"stem":132,"children":133,"page":26},"Phỏng vấn English","i-lucide-globe","\u002Fphong-van\u002Fenglish-interview","1.phong-van\u002F5.english-interview",[134,138,143,148],{"title":135,"path":136,"stem":137,"icon":130},"Tổng quan English","\u002Fphong-van\u002Fenglish-interview\u002Ftong-quan","1.phong-van\u002F5.english-interview\u002F1.tong-quan",{"title":139,"path":140,"stem":141,"icon":142},"Vocabulary","\u002Fphong-van\u002Fenglish-interview\u002Fvocabulary","1.phong-van\u002F5.english-interview\u002F2.vocabulary","i-lucide-book-a",{"title":144,"path":145,"stem":146,"icon":147},"Technical Q và A (EN)","\u002Fphong-van\u002Fenglish-interview\u002Ftechnical-en","1.phong-van\u002F5.english-interview\u002F3.technical-en","i-lucide-code",{"title":149,"path":150,"stem":151,"icon":152},"Behavioral (EN)","\u002Fphong-van\u002Fenglish-interview\u002Fbehavioral-en","1.phong-van\u002F5.english-interview\u002F4.behavioral-en","i-lucide-message-square-text",{"title":154,"icon":155,"path":156,"stem":157,"children":158},"Tự học","i-lucide-graduation-cap","\u002Ftu-hoc","2.tu-hoc",[159,161,287,310,333,357,384],{"title":154,"path":156,"stem":160,"icon":155},"2.tu-hoc\u002Findex",{"title":162,"icon":68,"path":163,"stem":164,"children":165},"Database","\u002Ftu-hoc\u002Fdatabase","2.tu-hoc\u002F1.database\u002Findex",[166,167,197,222,243,248],{"title":162,"path":163,"stem":164,"icon":68},{"title":168,"icon":91,"path":169,"stem":170,"children":171,"page":26},"SQL Server","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server","2.tu-hoc\u002F1.database\u002F2.sql-server",[172,177,182,187,192],{"title":173,"path":174,"stem":175,"icon":176},"1. Giới thiệu và Cài đặt","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F1.gioi-thieu-cai-dat","i-lucide-play-circle",{"title":178,"path":179,"stem":180,"icon":181},"2. Cú pháp cơ bản","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F2.cu-phap-co-ban","i-lucide-code-2",{"title":183,"path":184,"stem":185,"icon":186},"3. Truy vấn nâng cao","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F3.truy-van-nang-cao","i-lucide-git-merge",{"title":188,"path":189,"stem":190,"icon":191},"4. Đặc thù và Performance","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F4.dac-thu-performance","i-lucide-gauge",{"title":193,"path":194,"stem":195,"icon":196},"5. Q và A phỏng vấn","\u002Ftu-hoc\u002Fdatabase\u002Fsql-server\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F2.sql-server\u002F5.cau-hoi-phong-van","i-lucide-message-circle-question",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":26},"PostgreSQL","i-simple-icons-postgresql","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql","2.tu-hoc\u002F1.database\u002F3.postgresql",[203,206,209,212,215,218],{"title":173,"path":204,"stem":205,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":207,"stem":208,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F2.cu-phap-co-ban",{"title":183,"path":210,"stem":211,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F3.truy-van-nang-cao",{"title":188,"path":213,"stem":214,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F4.dac-thu-performance",{"title":193,"path":216,"stem":217,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F5.cau-hoi-phong-van",{"title":219,"path":220,"stem":221,"icon":96},"6. Tích hợp C# và Postgres","\u002Ftu-hoc\u002Fdatabase\u002Fpostgresql\u002Ftich-hop-csharp","2.tu-hoc\u002F1.database\u002F3.postgresql\u002F6.tich-hop-csharp",{"title":223,"icon":224,"path":225,"stem":226,"children":227,"page":26},"MySQL","i-simple-icons-mysql","\u002Ftu-hoc\u002Fdatabase\u002Fmysql","2.tu-hoc\u002F1.database\u002F4.mysql",[228,231,234,237,240],{"title":173,"path":229,"stem":230,"icon":176},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F1.database\u002F4.mysql\u002F1.gioi-thieu-cai-dat",{"title":178,"path":232,"stem":233,"icon":181},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcu-phap-co-ban","2.tu-hoc\u002F1.database\u002F4.mysql\u002F2.cu-phap-co-ban",{"title":183,"path":235,"stem":236,"icon":186},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Ftruy-van-nang-cao","2.tu-hoc\u002F1.database\u002F4.mysql\u002F3.truy-van-nang-cao",{"title":188,"path":238,"stem":239,"icon":191},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fdac-thu-performance","2.tu-hoc\u002F1.database\u002F4.mysql\u002F4.dac-thu-performance",{"title":193,"path":241,"stem":242,"icon":196},"\u002Ftu-hoc\u002Fdatabase\u002Fmysql\u002Fcau-hoi-phong-van","2.tu-hoc\u002F1.database\u002F4.mysql\u002F5.cau-hoi-phong-van",{"title":244,"path":245,"stem":246,"icon":247},"So sánh 3 RDBMS","\u002Ftu-hoc\u002Fdatabase\u002Fso-sanh","2.tu-hoc\u002F1.database\u002F5.so-sanh","i-lucide-columns-3",{"title":249,"path":250,"stem":251,"children":252,"icon":254},"Supabase (BaaS)","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002Findex",[253,255,259,264,269,274,278,283],{"title":249,"path":250,"stem":251,"icon":254},"i-simple-icons-supabase",{"title":256,"path":257,"stem":258,"icon":68},"1. Database","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fdatabase","2.tu-hoc\u002F1.database\u002F6.supabase\u002F1.database",{"title":260,"path":261,"stem":262,"icon":263},"2. Authentication","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fauthentication","2.tu-hoc\u002F1.database\u002F6.supabase\u002F2.authentication","i-lucide-key",{"title":265,"path":266,"stem":267,"icon":268},"3. Storage & Realtime","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fstorage-realtime","2.tu-hoc\u002F1.database\u002F6.supabase\u002F3.storage-realtime","i-lucide-zap",{"title":270,"path":271,"stem":272,"icon":273},"4. Edge Functions & AI","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Ffunctions-ai","2.tu-hoc\u002F1.database\u002F6.supabase\u002F4.functions-ai","i-lucide-brain",{"title":275,"path":276,"stem":277,"icon":181},"5. API & SDKs","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fapi-sdk","2.tu-hoc\u002F1.database\u002F6.supabase\u002F5.api-sdk",{"title":279,"path":280,"stem":281,"icon":282},"6. Platform & Deploy","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Fplatform-deploy","2.tu-hoc\u002F1.database\u002F6.supabase\u002F6.platform-deploy","i-lucide-cloud",{"title":284,"path":285,"stem":286,"icon":196},"7. Interview & Q&A","\u002Ftu-hoc\u002Fdatabase\u002Fsupabase\u002Finterview","2.tu-hoc\u002F1.database\u002F6.supabase\u002F7.interview",{"title":288,"icon":289,"path":290,"stem":291,"children":292},"TypeScript","i-simple-icons-typescript","\u002Ftu-hoc\u002Ftypescript","2.tu-hoc\u002F2.typescript\u002Findex",[293,294,297,301,306],{"title":288,"path":290,"stem":291,"icon":289},{"title":173,"path":295,"stem":296,"icon":176},"\u002Ftu-hoc\u002Ftypescript\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F2.typescript\u002F1.gioi-thieu-cai-dat",{"title":298,"path":299,"stem":300,"icon":81},"2. Type System","\u002Ftu-hoc\u002Ftypescript\u002Ftype-system","2.tu-hoc\u002F2.typescript\u002F2.type-system",{"title":302,"path":303,"stem":304,"icon":305},"3. Advanced types","\u002Ftu-hoc\u002Ftypescript\u002Fadvanced-types","2.tu-hoc\u002F2.typescript\u002F3.advanced-types","i-lucide-braces",{"title":307,"path":308,"stem":309,"icon":196},"4. Q và A phỏng vấn","\u002Ftu-hoc\u002Ftypescript\u002Fcau-hoi-phong-van","2.tu-hoc\u002F2.typescript\u002F4.cau-hoi-phong-van",{"title":311,"icon":81,"path":312,"stem":313,"children":314},"OOP","\u002Ftu-hoc\u002Foop","2.tu-hoc\u002F3.oop\u002Findex",[315,316,321,326,330],{"title":311,"path":312,"stem":313,"icon":81},{"title":317,"path":318,"stem":319,"icon":320},"1. Bốn tính chất","\u002Ftu-hoc\u002Foop\u002F4-tinh-chat","2.tu-hoc\u002F3.oop\u002F1.4-tinh-chat","i-lucide-circle-dot",{"title":322,"path":323,"stem":324,"icon":325},"2. SOLID","\u002Ftu-hoc\u002Foop\u002Fsolid","2.tu-hoc\u002F3.oop\u002F2.solid","i-lucide-shield",{"title":327,"path":328,"stem":329,"icon":106},"3. Design Pattern","\u002Ftu-hoc\u002Foop\u002Fdesign-pattern","2.tu-hoc\u002F3.oop\u002F3.design-pattern",{"title":307,"path":331,"stem":332,"icon":196},"\u002Ftu-hoc\u002Foop\u002Fcau-hoi-phong-van","2.tu-hoc\u002F3.oop\u002F4.cau-hoi-phong-van",{"title":334,"icon":305,"path":335,"stem":336,"children":337},"Generic","\u002Ftu-hoc\u002Fgeneric","2.tu-hoc\u002F4.generic\u002Findex",[338,339,344,349,354],{"title":334,"path":335,"stem":336,"icon":305},{"title":340,"path":341,"stem":342,"icon":343},"1. Khái niệm và cú pháp","\u002Ftu-hoc\u002Fgeneric\u002Fkhai-niem","2.tu-hoc\u002F4.generic\u002F1.khai-niem","i-lucide-book",{"title":345,"path":346,"stem":347,"icon":348},"2. Constraint và Variance","\u002Ftu-hoc\u002Fgeneric\u002Fconstraint-variance","2.tu-hoc\u002F4.generic\u002F2.constraint-variance","i-lucide-filter",{"title":350,"path":351,"stem":352,"icon":353},"3. C# vs TS","\u002Ftu-hoc\u002Fgeneric\u002Fso-sanh","2.tu-hoc\u002F4.generic\u002F3.so-sanh","i-lucide-git-compare",{"title":307,"path":355,"stem":356,"icon":196},"\u002Ftu-hoc\u002Fgeneric\u002Fcau-hoi-phong-van","2.tu-hoc\u002F4.generic\u002F4.cau-hoi-phong-van",{"title":358,"icon":359,"path":360,"stem":361,"children":362},"Nuxt 4","i-simple-icons-nuxt","\u002Ftu-hoc\u002Fnuxt-4","2.tu-hoc\u002F5.nuxt-4\u002Findex",[363,364,367,372,376,379],{"title":358,"path":360,"stem":361,"icon":359},{"title":173,"path":365,"stem":366,"icon":176},"\u002Ftu-hoc\u002Fnuxt-4\u002Fgioi-thieu-cai-dat","2.tu-hoc\u002F5.nuxt-4\u002F1.gioi-thieu-cai-dat",{"title":368,"path":369,"stem":370,"icon":371},"2. Routing và Rendering","\u002Ftu-hoc\u002Fnuxt-4\u002Frouting-rendering","2.tu-hoc\u002F5.nuxt-4\u002F2.routing-rendering","i-lucide-route",{"title":373,"path":374,"stem":375,"icon":91},"3. Data và Server","\u002Ftu-hoc\u002Fnuxt-4\u002Fdata-server","2.tu-hoc\u002F5.nuxt-4\u002F3.data-server",{"title":307,"path":377,"stem":378,"icon":196},"\u002Ftu-hoc\u002Fnuxt-4\u002Fcau-hoi-phong-van","2.tu-hoc\u002F5.nuxt-4\u002F4.cau-hoi-phong-van",{"title":380,"path":381,"stem":382,"icon":383},"5. Practical Todo App","\u002Ftu-hoc\u002Fnuxt-4\u002Fpractical-todo-app","2.tu-hoc\u002F5.nuxt-4\u002F5.practical-todo-app","i-lucide-check-square",{"title":385,"path":386,"stem":387,"children":388,"icon":390},"Tailwind CSS","\u002Ftu-hoc\u002Ftailwindcss","2.tu-hoc\u002F6.tailwindcss\u002Findex",[389,391,396,401,406,411,416],{"title":385,"path":386,"stem":387,"icon":390},"i-simple-icons-tailwindcss",{"title":392,"path":393,"stem":394,"icon":395},"1. Layout & Spacing","\u002Ftu-hoc\u002Ftailwindcss\u002Flayout-spacing","2.tu-hoc\u002F6.tailwindcss\u002F1.layout-spacing","i-lucide-layout",{"title":397,"path":398,"stem":399,"icon":400},"2. Typography & Colors","\u002Ftu-hoc\u002Ftailwindcss\u002Ftypography-colors","2.tu-hoc\u002F6.tailwindcss\u002F2.typography-colors","i-lucide-type",{"title":402,"path":403,"stem":404,"icon":405},"3. Interactive & Effects","\u002Ftu-hoc\u002Ftailwindcss\u002Finteractive-effects","2.tu-hoc\u002F6.tailwindcss\u002F3.interactive-effects","i-lucide-sparkles",{"title":407,"path":408,"stem":409,"icon":410},"4. Responsive & Dark Mode","\u002Ftu-hoc\u002Ftailwindcss\u002Fresponsive-darkmode","2.tu-hoc\u002F6.tailwindcss\u002F4.responsive-darkmode","i-lucide-monitor-smartphone",{"title":412,"path":413,"stem":414,"icon":415},"5. Customization & Theme","\u002Ftu-hoc\u002Ftailwindcss\u002Fcustomization","2.tu-hoc\u002F6.tailwindcss\u002F5.customization","i-lucide-settings-2",{"title":417,"path":418,"stem":419,"icon":181},"6. Practical Projects","\u002Ftu-hoc\u002Ftailwindcss\u002Fpractical-projects","2.tu-hoc\u002F6.tailwindcss\u002F6.practical-projects",{"id":421,"title":42,"body":422,"description":3994,"extension":3995,"links":3996,"meta":3997,"navigation":3998,"path":43,"seo":3999,"stem":44,"__hash__":4000},"docs\u002F1.phong-van\u002F2.lo-trinh\u002F3.ngay-3-csharp-nang-cao.md",{"type":423,"value":424,"toc":3939},"minimark",[425,430,434,492,498,501,505,510,601,605,637,640,660,664,782,789,891,943,947,1014,1016,1020,1024,1249,1256,1263,1293,1311,1315,1348,1362,1368,1409,1417,1455,1526,1528,1532,1536,1608,1612,1851,1855,1929,1934,1983,2007,2011,2055,2084,2089,2113,2120,2128,2156,2166,2172,2202,2205,2207,2211,2215,2224,2296,2310,2316,2437,2471,2475,2560,2564,2593,2706,2710,2824,2828,2887,2889,2893,2897,2968,2973,2987,2991,2994,3014,3017,3021,3059,3072,3074,3078,3082,3095,3099,3128,3131,3311,3316,3338,3353,3357,3414,3484,3488,3516,3579,3589,3634,3690,3698,3767,3772,3780,3788,3816,3821,3831,3833,3837,3918,3927,3929,3935],[426,427,429],"h2",{"id":428},"mục-tiêu-ngày-3","Mục tiêu ngày 3",[431,432,433],"p",{},"Sau ngày 3 bạn phải:",[435,436,437,445,452,463,470,481],"ul",{},[438,439,440,441,444],"li",{},"Hiểu ",[442,443,334],"strong",{}," ở mức \"vì sao tránh boxing\" + viết được Generic method\u002Fclass.",[438,446,447,448,451],{},"Chọn đúng ",[442,449,450],{},"collection"," cho từng use case + biết complexity.",[438,453,454,455,458,459,462],{},"Thành thạo ",[442,456,457],{},"LINQ"," + hiểu ",[442,460,461],{},"deferred execution"," ở mức state machine.",[438,464,465,466,469],{},"Phân biệt ",[442,467,468],{},"Delegate \u002F Action \u002F Func \u002F Event \u002F Lambda"," ở mức implementation.",[438,471,472,473,480],{},"Giải thích ",[442,474,475,479],{},[476,477,478],"code",{},"async\u002Fawait"," KHÔNG tạo thread mới"," + cơ chế state machine.",[438,482,483,484,487,488,491],{},"Biết khi nào ",[442,485,486],{},"Task vs Thread"," và bẫy ",[476,489,490],{},".Result"," deadlock.",[493,494,497],"callout",{"color":495,"icon":496},"primary","i-lucide-info","🟢 Intern | 🔵 Junior | 🟡 Mid | 🔴 Senior",[499,500],"hr",{},[426,502,504],{"id":503},"_1-generic-code-reuse-type-safety","1. Generic — code reuse + type safety",[506,507,509],"h3",{"id":508},"_11-vấn-đề-trước-khi-có-generic","1.1. Vấn đề trước khi có Generic",[493,511,512,523,583,586],{"color":495,"icon":496},[431,513,514,515,518,519,522],{},"🟢 Trước C# 2.0 (2005), không có Generic. Để có collection chứa nhiều loại, dùng ",[476,516,517],{},"ArrayList"," — lưu mọi thứ kiểu ",[476,520,521],{},"object",":",[524,525,530],"pre",{"className":526,"code":527,"language":528,"meta":529,"style":529},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ArrayList list = new();\nlist.Add(1);                  \u002F\u002F boxing! int → object\nlist.Add(\"hello\");\nlist.Add(new User());\n\nint x = (int)list[0];          \u002F\u002F unboxing!\nstring s = (string)list[1];    \u002F\u002F cast — nếu sai → runtime error\n\u002F\u002F list[0] = \"hello\"; — compile OK nhưng (int) sẽ runtime crash\n","csharp","",[476,531,532,540,546,552,558,565,571,577],{"__ignoreMap":529},[533,534,537],"span",{"class":535,"line":536},"line",1,[533,538,539],{},"ArrayList list = new();\n",[533,541,543],{"class":535,"line":542},2,[533,544,545],{},"list.Add(1);                  \u002F\u002F boxing! int → object\n",[533,547,549],{"class":535,"line":548},3,[533,550,551],{},"list.Add(\"hello\");\n",[533,553,555],{"class":535,"line":554},4,[533,556,557],{},"list.Add(new User());\n",[533,559,561],{"class":535,"line":560},5,[533,562,564],{"emptyLinePlaceholder":563},true,"\n",[533,566,568],{"class":535,"line":567},6,[533,569,570],{},"int x = (int)list[0];          \u002F\u002F unboxing!\n",[533,572,574],{"class":535,"line":573},7,[533,575,576],{},"string s = (string)list[1];    \u002F\u002F cast — nếu sai → runtime error\n",[533,578,580],{"class":535,"line":579},8,[533,581,582],{},"\u002F\u002F list[0] = \"hello\"; — compile OK nhưng (int) sẽ runtime crash\n",[431,584,585],{},"2 vấn đề:",[587,588,589,595],"ol",{},[438,590,591,594],{},[442,592,593],{},"Boxing\u002Funboxing"," đắt (đã học ngày 1).",[438,596,597,600],{},[442,598,599],{},"Không type-safe"," — bug chỉ phát hiện runtime.",[506,602,604],{"id":603},"_12-generic-giải-quyết","1.2. Generic giải quyết",[524,606,608],{"className":526,"code":607,"language":528,"meta":529,"style":529},"List\u003Cint> list = new();\nlist.Add(1);                  \u002F\u002F không boxing — int lưu thẳng\n\u002F\u002F list.Add(\"hello\");          \u002F\u002F ❌ compile error — type safety\n\nint x = list[0];               \u002F\u002F không cast\n",[476,609,610,615,620,628,632],{"__ignoreMap":529},[533,611,612],{"class":535,"line":536},[533,613,614],{},"List\u003Cint> list = new();\n",[533,616,617],{"class":535,"line":542},[533,618,619],{},"list.Add(1);                  \u002F\u002F không boxing — int lưu thẳng\n",[533,621,622,625],{"class":535,"line":548},[533,623,624],{},"\u002F\u002F list.Add(\"hello\");",[533,626,627],{},"          \u002F\u002F ❌ compile error — type safety\n",[533,629,630],{"class":535,"line":554},[533,631,564],{"emptyLinePlaceholder":563},[533,633,634],{"class":535,"line":560},[533,635,636],{},"int x = list[0];               \u002F\u002F không cast\n",[431,638,639],{},"3 lợi ích:",[587,641,642,648,654],{},[438,643,644,647],{},[442,645,646],{},"Type safety compile-time"," — không cast.",[438,649,650,653],{},[442,651,652],{},"Không boxing"," với value type — fast.",[438,655,656,659],{},[442,657,658],{},"Code reuse"," — 1 implementation cho mọi type.",[506,661,663],{"id":662},"_13-generic-method-class-interface","1.3. Generic method, class, interface",[524,665,667],{"className":526,"code":666,"language":528,"meta":529,"style":529},"\u002F\u002F Generic method\npublic static T Identity\u003CT>(T x) => x;\n\nIdentity(42);              \u002F\u002F T = int (inferred)\nIdentity\u003Cstring>(\"hi\");    \u002F\u002F T = string (explicit)\n\n\u002F\u002F Generic class\npublic class Box\u003CT> {\n    public T Value { get; }\n    public Box(T value) => Value = value;\n    public Box\u003CU> Map\u003CU>(Func\u003CT, U> fn) => new Box\u003CU>(fn(Value));\n}\n\nvar intBox = new Box\u003Cint>(42);\nvar strBox = intBox.Map(n => n.ToString());     \u002F\u002F Box\u003Cstring>\n\n\u002F\u002F Generic interface\npublic interface IRepository\u003CT> where T : class {\n    Task\u003CT?> GetByIdAsync(int id);\n    Task AddAsync(T entity);\n}\n",[476,668,669,674,679,683,688,693,697,702,707,713,719,725,731,736,742,748,753,759,765,771,777],{"__ignoreMap":529},[533,670,671],{"class":535,"line":536},[533,672,673],{},"\u002F\u002F Generic method\n",[533,675,676],{"class":535,"line":542},[533,677,678],{},"public static T Identity\u003CT>(T x) => x;\n",[533,680,681],{"class":535,"line":548},[533,682,564],{"emptyLinePlaceholder":563},[533,684,685],{"class":535,"line":554},[533,686,687],{},"Identity(42);              \u002F\u002F T = int (inferred)\n",[533,689,690],{"class":535,"line":560},[533,691,692],{},"Identity\u003Cstring>(\"hi\");    \u002F\u002F T = string (explicit)\n",[533,694,695],{"class":535,"line":567},[533,696,564],{"emptyLinePlaceholder":563},[533,698,699],{"class":535,"line":573},[533,700,701],{},"\u002F\u002F Generic class\n",[533,703,704],{"class":535,"line":579},[533,705,706],{},"public class Box\u003CT> {\n",[533,708,710],{"class":535,"line":709},9,[533,711,712],{},"    public T Value { get; }\n",[533,714,716],{"class":535,"line":715},10,[533,717,718],{},"    public Box(T value) => Value = value;\n",[533,720,722],{"class":535,"line":721},11,[533,723,724],{},"    public Box\u003CU> Map\u003CU>(Func\u003CT, U> fn) => new Box\u003CU>(fn(Value));\n",[533,726,728],{"class":535,"line":727},12,[533,729,730],{},"}\n",[533,732,734],{"class":535,"line":733},13,[533,735,564],{"emptyLinePlaceholder":563},[533,737,739],{"class":535,"line":738},14,[533,740,741],{},"var intBox = new Box\u003Cint>(42);\n",[533,743,745],{"class":535,"line":744},15,[533,746,747],{},"var strBox = intBox.Map(n => n.ToString());     \u002F\u002F Box\u003Cstring>\n",[533,749,751],{"class":535,"line":750},16,[533,752,564],{"emptyLinePlaceholder":563},[533,754,756],{"class":535,"line":755},17,[533,757,758],{},"\u002F\u002F Generic interface\n",[533,760,762],{"class":535,"line":761},18,[533,763,764],{},"public interface IRepository\u003CT> where T : class {\n",[533,766,768],{"class":535,"line":767},19,[533,769,770],{},"    Task\u003CT?> GetByIdAsync(int id);\n",[533,772,774],{"class":535,"line":773},20,[533,775,776],{},"    Task AddAsync(T entity);\n",[533,778,780],{"class":535,"line":779},21,[533,781,730],{},[506,783,785,786],{"id":784},"_14-constraint-where-t","1.4. Constraint — ",[476,787,788],{},"where T : ...",[790,791,792,805],"table",{},[793,794,795],"thead",{},[796,797,798,802],"tr",{},[799,800,801],"th",{},"Constraint",[799,803,804],{},"Ý nghĩa",[806,807,808,819,829,839,849,859,870,881],"tbody",{},[796,809,810,816],{},[811,812,813],"td",{},[476,814,815],{},"where T : class",[811,817,818],{},"T là reference type",[796,820,821,826],{},[811,822,823],{},[476,824,825],{},"where T : struct",[811,827,828],{},"T là value type",[796,830,831,836],{},[811,832,833],{},[476,834,835],{},"where T : new()",[811,837,838],{},"T có constructor không tham số",[796,840,841,846],{},[811,842,843],{},[476,844,845],{},"where T : IComparable\u003CT>",[811,847,848],{},"T implement interface",[796,850,851,856],{},[811,852,853],{},[476,854,855],{},"where T : BaseClass",[811,857,858],{},"T kế thừa class cha",[796,860,861,867],{},[811,862,863,866],{},[476,864,865],{},"where T : enum"," (C# 7.3+)",[811,868,869],{},"T là enum",[796,871,872,878],{},[811,873,874,877],{},[476,875,876],{},"where T : INumber\u003CT>"," (C# 11+)",[811,879,880],{},"T support operator math",[796,882,883,888],{},[811,884,885],{},[476,886,887],{},"where T : U",[811,889,890],{},"T là U hoặc subtype",[524,892,894],{"className":526,"code":893,"language":528,"meta":529,"style":529},"\u002F\u002F T phải có constructor để new() được\npublic class Factory\u003CT> where T : new() {\n    public T Create() => new T();\n}\n\n\u002F\u002F Combine — Repository chỉ chấp nhận class implement IEntity, có ctor\npublic abstract class Repository\u003CT> where T : class, IEntity, new() {\n    public T CreateBlank() => new T();\n    \u002F\u002F ...\n}\n",[476,895,896,901,906,911,915,919,924,929,934,939],{"__ignoreMap":529},[533,897,898],{"class":535,"line":536},[533,899,900],{},"\u002F\u002F T phải có constructor để new() được\n",[533,902,903],{"class":535,"line":542},[533,904,905],{},"public class Factory\u003CT> where T : new() {\n",[533,907,908],{"class":535,"line":548},[533,909,910],{},"    public T Create() => new T();\n",[533,912,913],{"class":535,"line":554},[533,914,730],{},[533,916,917],{"class":535,"line":560},[533,918,564],{"emptyLinePlaceholder":563},[533,920,921],{"class":535,"line":567},[533,922,923],{},"\u002F\u002F Combine — Repository chỉ chấp nhận class implement IEntity, có ctor\n",[533,925,926],{"class":535,"line":573},[533,927,928],{},"public abstract class Repository\u003CT> where T : class, IEntity, new() {\n",[533,930,931],{"class":535,"line":579},[533,932,933],{},"    public T CreateBlank() => new T();\n",[533,935,936],{"class":535,"line":709},[533,937,938],{},"    \u002F\u002F ...\n",[533,940,941],{"class":535,"line":715},[533,942,730],{},[506,944,946],{"id":945},"_15-generic-specialization-internals","1.5. 🔴 Generic specialization — internals",[493,948,950,967,986,993,999],{"color":949,"icon":268},"warning",[431,951,952,953,963,964,522],{},"🔴 ",[442,954,955,956,959,960],{},"Khi compile ",[476,957,958],{},"List\u003Cint>"," vs ",[476,961,962],{},"List\u003Cstring>"," — CLR sinh ",[442,965,966],{},"2 IL khác nhau",[435,968,969,978],{},[438,970,971,973,974,977],{},[476,972,958],{},": dùng ",[476,975,976],{},"int"," (4 bytes) trực tiếp trong array nội bộ — không boxing.",[438,979,980,973,982,985],{},[476,981,962],{},[476,983,984],{},"object reference"," (8 bytes pointer) — share IL với mọi reference type.",[431,987,988,989,992],{},"→ Mỗi ",[442,990,991],{},"value type"," instantiation tạo 1 specialized version trong JIT — fast & memory-efficient.",[431,994,988,995,998],{},[442,996,997],{},"reference type"," instantiation share 1 implementation — vì pointer luôn cùng size.",[431,1000,1001,1002,1005,1006,1009,1010,1013],{},"Khác Java: Java ",[442,1003,1004],{},"type erasure"," — ",[476,1007,1008],{},"List\u003CInteger>"," runtime = ",[476,1011,1012],{},"List\u003CObject>",", vẫn boxing.",[499,1015],{},[426,1017,1019],{"id":1018},"_2-collections-chọn-cho-đúng","2. Collections — chọn cho đúng",[506,1021,1023],{"id":1022},"_21-bảng-tổng-hợp","2.1. Bảng tổng hợp",[790,1025,1026,1048],{},[793,1027,1028],{},[796,1029,1030,1033,1036,1039,1042,1045],{},[799,1031,1032],{},"Khi cần",[799,1034,1035],{},"Collection",[799,1037,1038],{},"Get",[799,1040,1041],{},"Add",[799,1043,1044],{},"Remove",[799,1046,1047],{},"Note",[806,1049,1050,1072,1092,1112,1132,1152,1172,1190,1209,1229],{},[796,1051,1052,1055,1060,1063,1066,1069],{},[811,1053,1054],{},"Mảng động, index",[811,1056,1057],{},[476,1058,1059],{},"List\u003CT>",[811,1061,1062],{},"O(1)",[811,1064,1065],{},"O(1)* cuối, O(n) giữa",[811,1067,1068],{},"O(n)",[811,1070,1071],{},"Resize ×2 khi đầy",[796,1073,1074,1077,1082,1085,1087,1089],{},[811,1075,1076],{},"Key → Value",[811,1078,1079],{},[476,1080,1081],{},"Dictionary\u003CK,V>",[811,1083,1084],{},"O(1) avg",[811,1086,1084],{},[811,1088,1084],{},[811,1090,1091],{},"Hash collision",[796,1093,1094,1097,1102,1105,1107,1109],{},[811,1095,1096],{},"Tập unique",[811,1098,1099],{},[476,1100,1101],{},"HashSet\u003CT>",[811,1103,1104],{},"–",[811,1106,1084],{},[811,1108,1084],{},[811,1110,1111],{},"Membership test",[796,1113,1114,1117,1122,1124,1127,1130],{},[811,1115,1116],{},"FIFO",[811,1118,1119],{},[476,1120,1121],{},"Queue\u003CT>",[811,1123,1104],{},[811,1125,1126],{},"O(1) Enqueue",[811,1128,1129],{},"O(1) Dequeue",[811,1131],{},[796,1133,1134,1137,1142,1144,1147,1150],{},[811,1135,1136],{},"LIFO",[811,1138,1139],{},[476,1140,1141],{},"Stack\u003CT>",[811,1143,1104],{},[811,1145,1146],{},"O(1) Push",[811,1148,1149],{},"O(1) Pop",[811,1151],{},[796,1153,1154,1157,1162,1164,1167,1169],{},[811,1155,1156],{},"Sorted by key",[811,1158,1159],{},[476,1160,1161],{},"SortedDictionary\u003CK,V>",[811,1163,1104],{},[811,1165,1166],{},"O(log n)",[811,1168,1166],{},[811,1170,1171],{},"Red-black tree",[796,1173,1174,1177,1182,1184,1186,1188],{},[811,1175,1176],{},"Sorted set",[811,1178,1179],{},[476,1180,1181],{},"SortedSet\u003CT>",[811,1183,1104],{},[811,1185,1166],{},[811,1187,1166],{},[811,1189],{},[796,1191,1192,1195,1200,1202,1204,1206],{},[811,1193,1194],{},"Priority",[811,1196,1197],{},[476,1198,1199],{},"PriorityQueue\u003CT,P>",[811,1201,1104],{},[811,1203,1166],{},[811,1205,1166],{},[811,1207,1208],{},"Min-heap default",[796,1210,1211,1214,1219,1221,1224,1226],{},[811,1212,1213],{},"Linked nodes",[811,1215,1216],{},[476,1217,1218],{},"LinkedList\u003CT>",[811,1220,1068],{},[811,1222,1223],{},"O(1) ở node",[811,1225,1223],{},[811,1227,1228],{},"Doubly-linked",[796,1230,1231,1234,1239,1241,1244,1246],{},[811,1232,1233],{},"Đa luồng",[811,1235,1236],{},[476,1237,1238],{},"ConcurrentDictionary",[811,1240,1104],{},[811,1242,1243],{},"O(1) avg lock-free",[811,1245,1104],{},[811,1247,1248],{},"Thread-safe",[431,1250,1251,1252,1255],{},"*Add cuối O(1) ",[442,1253,1254],{},"amortized"," — vì resize chi phí được trải đều qua nhiều lần add.",[506,1257,1259,1260],{"id":1258},"_22-resize-của-list","2.2. 🟡 Resize của List",[1261,1262],"t",{},[524,1264,1266],{"className":526,"code":1265,"language":528,"meta":529,"style":529},"var list = new List\u003Cint>();    \u002F\u002F Capacity = 0\nlist.Add(1);                   \u002F\u002F Capacity = 4 (default initial)\nlist.Add(2); list.Add(3); list.Add(4);    \u002F\u002F Capacity = 4\nlist.Add(5);                   \u002F\u002F Capacity = 8 (×2)\n\u002F\u002F ... đầy 8 → next 16 → 32 → 64...\n",[476,1267,1268,1273,1278,1283,1288],{"__ignoreMap":529},[533,1269,1270],{"class":535,"line":536},[533,1271,1272],{},"var list = new List\u003Cint>();    \u002F\u002F Capacity = 0\n",[533,1274,1275],{"class":535,"line":542},[533,1276,1277],{},"list.Add(1);                   \u002F\u002F Capacity = 4 (default initial)\n",[533,1279,1280],{"class":535,"line":548},[533,1281,1282],{},"list.Add(2); list.Add(3); list.Add(4);    \u002F\u002F Capacity = 4\n",[533,1284,1285],{"class":535,"line":554},[533,1286,1287],{},"list.Add(5);                   \u002F\u002F Capacity = 8 (×2)\n",[533,1289,1290],{"class":535,"line":560},[533,1291,1292],{},"\u002F\u002F ... đầy 8 → next 16 → 32 → 64...\n",[493,1294,1295,1302],{"color":495,"icon":496},[431,1296,1297,1298,1301],{},"🟡 ",[442,1299,1300],{},"Nếu biết trước size",", pre-allocate giảm overhead resize:",[524,1303,1305],{"className":526,"code":1304,"language":528,"meta":529,"style":529},"var list = new List\u003Cint>(capacity: 10_000);  \u002F\u002F tránh resize 11 lần\n",[476,1306,1307],{"__ignoreMap":529},[533,1308,1309],{"class":535,"line":536},[533,1310,1304],{},[506,1312,1314],{"id":1313},"_23-dictionary-hash-collision","2.3. Dictionary — hash collision",[493,1316,1317,1323,1331,1337],{"color":949,"icon":268},[431,1318,1297,1319,1322],{},[442,1320,1321],{},"Dictionary internals",": dùng hash → bucket → linked list (separate chaining).",[524,1324,1329],{"className":1325,"code":1327,"language":1328},[1326],"language-text","GetHashCode(key) % bucketCount → bucket index\nbucket → list các (key, value) có cùng hash\n","text",[476,1330,1327],{"__ignoreMap":529},[431,1332,1333,1334,1336],{},"Worst case: tất cả key cùng hash → ",[442,1335,1068],{}," thay vì O(1). Hiếm với hash tốt.",[431,1338,1339,1340,1343,1344,1347],{},"→ Đó là vì sao override ",[476,1341,1342],{},"Equals"," thì PHẢI override ",[476,1345,1346],{},"GetHashCode"," (đã học ngày 1) — nếu 2 key equals nhưng hash khác → Dictionary mất hẳn data.",[506,1349,1351,1352,959,1355,959,1358,1361],{"id":1350},"_24-ienumerable-vs-icollection-vs-ilist-kế-thừa","2.4. ",[476,1353,1354],{},"IEnumerable",[476,1356,1357],{},"ICollection",[476,1359,1360],{},"IList"," — kế thừa",[524,1363,1366],{"className":1364,"code":1365,"language":1328},[1326],"IEnumerable\u003CT>            ← chỉ foreach\n    ↓\nICollection\u003CT>            ← thêm Count, Add, Remove\n    ↓\nIList\u003CT>                  ← thêm indexer [i], Insert, RemoveAt\n    ↓\nList\u003CT>                   ← concrete\n",[476,1367,1365],{"__ignoreMap":529},[493,1369,1370,1377,1406],{"color":495,"icon":496},[431,1371,1372,1373,1376],{},"🔵 ",[442,1374,1375],{},"Best practice expose API",": dùng interface nhỏ nhất đủ dùng.",[435,1378,1379,1386,1397],{},[438,1380,1381,1382,1385],{},"Caller chỉ cần iterate → expose ",[476,1383,1384],{},"IEnumerable\u003CT>"," (read-only, lazy OK).",[438,1387,1388,1389,1392,1393,1396],{},"Caller cần Count → ",[476,1390,1391],{},"IReadOnlyCollection\u003CT>"," hoặc ",[476,1394,1395],{},"ICollection\u003CT>",".",[438,1398,1399,1400,1392,1403,1396],{},"Caller cần index → ",[476,1401,1402],{},"IReadOnlyList\u003CT>",[476,1404,1405],{},"IList\u003CT>",[431,1407,1408],{},"Hidden API surface = ít breaking change khi đổi implementation.",[506,1410,1412,1413,1416],{"id":1411},"_25-yield-return-iterator-lazy","2.5. ",[476,1414,1415],{},"yield return"," — iterator lazy",[524,1418,1420],{"className":526,"code":1419,"language":528,"meta":529,"style":529},"public IEnumerable\u003Cint> EvenNumbers(int max) {\n    for (int i = 0; i \u003C= max; i += 2) {\n        yield return i;\n    }\n}\n\nforeach (var n in EvenNumbers(10)) Console.WriteLine(n);\n",[476,1421,1422,1427,1432,1437,1442,1446,1450],{"__ignoreMap":529},[533,1423,1424],{"class":535,"line":536},[533,1425,1426],{},"public IEnumerable\u003Cint> EvenNumbers(int max) {\n",[533,1428,1429],{"class":535,"line":542},[533,1430,1431],{},"    for (int i = 0; i \u003C= max; i += 2) {\n",[533,1433,1434],{"class":535,"line":548},[533,1435,1436],{},"        yield return i;\n",[533,1438,1439],{"class":535,"line":554},[533,1440,1441],{},"    }\n",[533,1443,1444],{"class":535,"line":560},[533,1445,730],{},[533,1447,1448],{"class":535,"line":567},[533,1449,564],{"emptyLinePlaceholder":563},[533,1451,1452],{"class":535,"line":573},[533,1453,1454],{},"foreach (var n in EvenNumbers(10)) Console.WriteLine(n);\n",[493,1456,1457,1481,1488],{"color":949,"icon":268},[431,1458,1297,1459,1465,1466,1469,1470,1473,1474,1477,1478,1480],{},[442,1460,1461,1462,522],{},"Cơ chế ",[476,1463,1464],{},"yield"," compiler sinh ra ",[442,1467,1468],{},"state machine"," class implement ",[476,1471,1472],{},"IEnumerator\u003Cint>",". Mỗi ",[476,1475,1476],{},"MoveNext()"," chạy đến ",[476,1479,1415],{}," tiếp theo. State (i, vị trí execution) được lưu trong class.",[431,1482,1483,1484,1487],{},"Lợi ích: ",[442,1485,1486],{},"lazy"," — chỉ generate khi caller cần. Có thể infinite:",[524,1489,1491],{"className":526,"code":1490,"language":528,"meta":529,"style":529},"public IEnumerable\u003Cint> Naturals() {\n    int i = 1;\n    while (true) yield return i++;\n}\n\n\u002F\u002F Lấy 10 số đầu, không tràn memory\nforeach (var n in Naturals().Take(10)) Console.WriteLine(n);\n",[476,1492,1493,1498,1503,1508,1512,1516,1521],{"__ignoreMap":529},[533,1494,1495],{"class":535,"line":536},[533,1496,1497],{},"public IEnumerable\u003Cint> Naturals() {\n",[533,1499,1500],{"class":535,"line":542},[533,1501,1502],{},"    int i = 1;\n",[533,1504,1505],{"class":535,"line":548},[533,1506,1507],{},"    while (true) yield return i++;\n",[533,1509,1510],{"class":535,"line":554},[533,1511,730],{},[533,1513,1514],{"class":535,"line":560},[533,1515,564],{"emptyLinePlaceholder":563},[533,1517,1518],{"class":535,"line":567},[533,1519,1520],{},"\u002F\u002F Lấy 10 số đầu, không tràn memory\n",[533,1522,1523],{"class":535,"line":573},[533,1524,1525],{},"foreach (var n in Naturals().Take(10)) Console.WriteLine(n);\n",[499,1527],{},[426,1529,1531],{"id":1530},"_3-linq-language-integrated-query","3. LINQ — Language Integrated Query",[506,1533,1535],{"id":1534},"_31-linq-là-gì","3.1. LINQ là gì?",[493,1537,1538,1551,1605],{"color":495,"icon":496},[431,1539,1540,1541,1543,1544,1546,1547,1550],{},"🟢 ",[442,1542,457],{}," = bộ extension method trên ",[476,1545,1384],{}," và ",[476,1548,1549],{},"IQueryable\u003CT>"," cho query data style functional. 2 cú pháp:",[524,1552,1554],{"className":526,"code":1553,"language":528,"meta":529,"style":529},"\u002F\u002F Method syntax (phổ biến)\nvar hcm = users.Where(u => u.City == \"HCM\")\n               .OrderBy(u => u.Age)\n               .Select(u => u.Name);\n\n\u002F\u002F Query syntax (giống SQL)\nvar hcm = from u in users\n          where u.City == \"HCM\"\n          orderby u.Age\n          select u.Name;\n",[476,1555,1556,1561,1566,1571,1576,1580,1585,1590,1595,1600],{"__ignoreMap":529},[533,1557,1558],{"class":535,"line":536},[533,1559,1560],{},"\u002F\u002F Method syntax (phổ biến)\n",[533,1562,1563],{"class":535,"line":542},[533,1564,1565],{},"var hcm = users.Where(u => u.City == \"HCM\")\n",[533,1567,1568],{"class":535,"line":548},[533,1569,1570],{},"               .OrderBy(u => u.Age)\n",[533,1572,1573],{"class":535,"line":554},[533,1574,1575],{},"               .Select(u => u.Name);\n",[533,1577,1578],{"class":535,"line":560},[533,1579,564],{"emptyLinePlaceholder":563},[533,1581,1582],{"class":535,"line":567},[533,1583,1584],{},"\u002F\u002F Query syntax (giống SQL)\n",[533,1586,1587],{"class":535,"line":573},[533,1588,1589],{},"var hcm = from u in users\n",[533,1591,1592],{"class":535,"line":579},[533,1593,1594],{},"          where u.City == \"HCM\"\n",[533,1596,1597],{"class":535,"line":709},[533,1598,1599],{},"          orderby u.Age\n",[533,1601,1602],{"class":535,"line":715},[533,1603,1604],{},"          select u.Name;\n",[431,1606,1607],{},"Compiler convert query syntax → method syntax. Hoàn toàn tương đương.",[506,1609,1611],{"id":1610},"_32-method-quan-trọng","3.2. Method quan trọng",[524,1613,1615],{"className":526,"code":1614,"language":528,"meta":529,"style":529},"var users = new List\u003CUser> {\n    new(\"Alice\", 25, \"HCM\"),\n    new(\"Bob\",   30, \"HN\"),\n    new(\"Charlie\", 22, \"HCM\"),\n};\n\n\u002F\u002F Filter\nusers.Where(u => u.City == \"HCM\");\n\n\u002F\u002F Project\nusers.Select(u => new { u.Name, u.Age });\n\n\u002F\u002F Sort\nusers.OrderBy(u => u.City).ThenByDescending(u => u.Age);\n\n\u002F\u002F Group\nusers.GroupBy(u => u.City)\n     .Select(g => new { City = g.Key, Count = g.Count() });\n\n\u002F\u002F Aggregate\nusers.Count();\nusers.Sum(u => u.Age);\nusers.Average(u => u.Age);\nusers.Min(u => u.Age);\nusers.Max(u => u.Age);\n\n\u002F\u002F Predicate\nusers.Any(u => u.Age > 25);          \u002F\u002F có ai > 25?\nusers.All(u => u.Age >= 18);         \u002F\u002F tất cả >= 18?\n\n\u002F\u002F Element\nusers.First(u => u.Name == \"Alice\");           \u002F\u002F không có → exception\nusers.FirstOrDefault(u => u.Name == \"X\");      \u002F\u002F không có → null\u002Fdefault\nusers.Single(u => u.City == \"HCM\");            \u002F\u002F CHÍNH XÁC 1 phần tử, khác → exception\n\n\u002F\u002F Set\nusers.Distinct();\nusers.Skip(2).Take(3);                          \u002F\u002F pagination\n\n\u002F\u002F Join\nvar orders = new List\u003COrder> { \u002F*...*\u002F };\nusers.Join(orders,\n    u => u.Id, o => o.UserId,\n    (u, o) => new { u.Name, o.Total });\n",[476,1616,1617,1622,1627,1632,1637,1642,1646,1651,1656,1660,1665,1670,1674,1679,1684,1688,1693,1698,1703,1707,1712,1717,1723,1729,1735,1741,1746,1752,1758,1764,1769,1775,1781,1787,1793,1798,1804,1810,1816,1821,1827,1833,1839,1845],{"__ignoreMap":529},[533,1618,1619],{"class":535,"line":536},[533,1620,1621],{},"var users = new List\u003CUser> {\n",[533,1623,1624],{"class":535,"line":542},[533,1625,1626],{},"    new(\"Alice\", 25, \"HCM\"),\n",[533,1628,1629],{"class":535,"line":548},[533,1630,1631],{},"    new(\"Bob\",   30, \"HN\"),\n",[533,1633,1634],{"class":535,"line":554},[533,1635,1636],{},"    new(\"Charlie\", 22, \"HCM\"),\n",[533,1638,1639],{"class":535,"line":560},[533,1640,1641],{},"};\n",[533,1643,1644],{"class":535,"line":567},[533,1645,564],{"emptyLinePlaceholder":563},[533,1647,1648],{"class":535,"line":573},[533,1649,1650],{},"\u002F\u002F Filter\n",[533,1652,1653],{"class":535,"line":579},[533,1654,1655],{},"users.Where(u => u.City == \"HCM\");\n",[533,1657,1658],{"class":535,"line":709},[533,1659,564],{"emptyLinePlaceholder":563},[533,1661,1662],{"class":535,"line":715},[533,1663,1664],{},"\u002F\u002F Project\n",[533,1666,1667],{"class":535,"line":721},[533,1668,1669],{},"users.Select(u => new { u.Name, u.Age });\n",[533,1671,1672],{"class":535,"line":727},[533,1673,564],{"emptyLinePlaceholder":563},[533,1675,1676],{"class":535,"line":733},[533,1677,1678],{},"\u002F\u002F Sort\n",[533,1680,1681],{"class":535,"line":738},[533,1682,1683],{},"users.OrderBy(u => u.City).ThenByDescending(u => u.Age);\n",[533,1685,1686],{"class":535,"line":744},[533,1687,564],{"emptyLinePlaceholder":563},[533,1689,1690],{"class":535,"line":750},[533,1691,1692],{},"\u002F\u002F Group\n",[533,1694,1695],{"class":535,"line":755},[533,1696,1697],{},"users.GroupBy(u => u.City)\n",[533,1699,1700],{"class":535,"line":761},[533,1701,1702],{},"     .Select(g => new { City = g.Key, Count = g.Count() });\n",[533,1704,1705],{"class":535,"line":767},[533,1706,564],{"emptyLinePlaceholder":563},[533,1708,1709],{"class":535,"line":773},[533,1710,1711],{},"\u002F\u002F Aggregate\n",[533,1713,1714],{"class":535,"line":779},[533,1715,1716],{},"users.Count();\n",[533,1718,1720],{"class":535,"line":1719},22,[533,1721,1722],{},"users.Sum(u => u.Age);\n",[533,1724,1726],{"class":535,"line":1725},23,[533,1727,1728],{},"users.Average(u => u.Age);\n",[533,1730,1732],{"class":535,"line":1731},24,[533,1733,1734],{},"users.Min(u => u.Age);\n",[533,1736,1738],{"class":535,"line":1737},25,[533,1739,1740],{},"users.Max(u => u.Age);\n",[533,1742,1744],{"class":535,"line":1743},26,[533,1745,564],{"emptyLinePlaceholder":563},[533,1747,1749],{"class":535,"line":1748},27,[533,1750,1751],{},"\u002F\u002F Predicate\n",[533,1753,1755],{"class":535,"line":1754},28,[533,1756,1757],{},"users.Any(u => u.Age > 25);          \u002F\u002F có ai > 25?\n",[533,1759,1761],{"class":535,"line":1760},29,[533,1762,1763],{},"users.All(u => u.Age >= 18);         \u002F\u002F tất cả >= 18?\n",[533,1765,1767],{"class":535,"line":1766},30,[533,1768,564],{"emptyLinePlaceholder":563},[533,1770,1772],{"class":535,"line":1771},31,[533,1773,1774],{},"\u002F\u002F Element\n",[533,1776,1778],{"class":535,"line":1777},32,[533,1779,1780],{},"users.First(u => u.Name == \"Alice\");           \u002F\u002F không có → exception\n",[533,1782,1784],{"class":535,"line":1783},33,[533,1785,1786],{},"users.FirstOrDefault(u => u.Name == \"X\");      \u002F\u002F không có → null\u002Fdefault\n",[533,1788,1790],{"class":535,"line":1789},34,[533,1791,1792],{},"users.Single(u => u.City == \"HCM\");            \u002F\u002F CHÍNH XÁC 1 phần tử, khác → exception\n",[533,1794,1796],{"class":535,"line":1795},35,[533,1797,564],{"emptyLinePlaceholder":563},[533,1799,1801],{"class":535,"line":1800},36,[533,1802,1803],{},"\u002F\u002F Set\n",[533,1805,1807],{"class":535,"line":1806},37,[533,1808,1809],{},"users.Distinct();\n",[533,1811,1813],{"class":535,"line":1812},38,[533,1814,1815],{},"users.Skip(2).Take(3);                          \u002F\u002F pagination\n",[533,1817,1819],{"class":535,"line":1818},39,[533,1820,564],{"emptyLinePlaceholder":563},[533,1822,1824],{"class":535,"line":1823},40,[533,1825,1826],{},"\u002F\u002F Join\n",[533,1828,1830],{"class":535,"line":1829},41,[533,1831,1832],{},"var orders = new List\u003COrder> { \u002F*...*\u002F };\n",[533,1834,1836],{"class":535,"line":1835},42,[533,1837,1838],{},"users.Join(orders,\n",[533,1840,1842],{"class":535,"line":1841},43,[533,1843,1844],{},"    u => u.Id, o => o.UserId,\n",[533,1846,1848],{"class":535,"line":1847},44,[533,1849,1850],{},"    (u, o) => new { u.Name, o.Total });\n",[506,1852,1854],{"id":1853},"_33-ienumerable-vs-iqueryable-phân-biệt-quan-trọng","3.3. 🟡 IEnumerable vs IQueryable — phân biệt quan trọng",[493,1856,1858,1865],{"color":949,"icon":1857},"i-lucide-star",[431,1859,1860,1861,1864],{},"⭐ ",[442,1862,1863],{},"Câu PV cực hay"," — đặc biệt với .NET có EF Core.",[790,1866,1867,1881],{},[793,1868,1869],{},[796,1870,1871,1873,1877],{},[799,1872],{},[799,1874,1875],{},[476,1876,1384],{},[799,1878,1879],{},[476,1880,1549],{},[806,1882,1883,1900,1918],{},[796,1884,1885,1888,1894],{},[811,1886,1887],{},"Query chạy ở đâu",[811,1889,1890,1893],{},[442,1891,1892],{},"In-memory"," (client)",[811,1895,1896,1899],{},[442,1897,1898],{},"Dịch sang SQL",", chạy ở DB",[796,1901,1902,1908,1911],{},[811,1903,1904,1905],{},"Khi gọi ",[476,1906,1907],{},".Where(x => x.Age > 18)",[811,1909,1910],{},"Filter trong RAM",[811,1912,1913,1914,1917],{},"Generate ",[476,1915,1916],{},"WHERE age > 18"," trong SQL",[796,1919,1920,1923,1926],{},[811,1921,1922],{},"Lợi điểm",[811,1924,1925],{},"Đơn giản, dùng cho list nhỏ",[811,1927,1928],{},"Push filter xuống DB → ít data về client",[431,1930,1931],{},[442,1932,1933],{},"Ví dụ tai hại nếu nhầm:",[524,1935,1937],{"className":526,"code":1936,"language":528,"meta":529,"style":529},"\u002F\u002F ❌ Lấy HẾT user về client rồi mới filter\nIEnumerable\u003CUser> all = dbContext.Users;    \u002F\u002F .AsEnumerable() ép thành IEnumerable\nvar hcm = all.Where(u => u.City == \"HCM\").ToList();\n\u002F\u002F → SQL: SELECT * FROM Users (lấy hết 1 triệu user về RAM!)\n\n\u002F\u002F ✅ Filter ở DB\nIQueryable\u003CUser> q = dbContext.Users;       \u002F\u002F mặc định là IQueryable\nvar hcm = q.Where(u => u.City == \"HCM\").ToList();\n\u002F\u002F → SQL: SELECT * FROM Users WHERE City = 'HCM' (chỉ lấy data cần)\n",[476,1938,1939,1944,1949,1954,1959,1963,1968,1973,1978],{"__ignoreMap":529},[533,1940,1941],{"class":535,"line":536},[533,1942,1943],{},"\u002F\u002F ❌ Lấy HẾT user về client rồi mới filter\n",[533,1945,1946],{"class":535,"line":542},[533,1947,1948],{},"IEnumerable\u003CUser> all = dbContext.Users;    \u002F\u002F .AsEnumerable() ép thành IEnumerable\n",[533,1950,1951],{"class":535,"line":548},[533,1952,1953],{},"var hcm = all.Where(u => u.City == \"HCM\").ToList();\n",[533,1955,1956],{"class":535,"line":554},[533,1957,1958],{},"\u002F\u002F → SQL: SELECT * FROM Users (lấy hết 1 triệu user về RAM!)\n",[533,1960,1961],{"class":535,"line":560},[533,1962,564],{"emptyLinePlaceholder":563},[533,1964,1965],{"class":535,"line":567},[533,1966,1967],{},"\u002F\u002F ✅ Filter ở DB\n",[533,1969,1970],{"class":535,"line":573},[533,1971,1972],{},"IQueryable\u003CUser> q = dbContext.Users;       \u002F\u002F mặc định là IQueryable\n",[533,1974,1975],{"class":535,"line":579},[533,1976,1977],{},"var hcm = q.Where(u => u.City == \"HCM\").ToList();\n",[533,1979,1980],{"class":535,"line":709},[533,1981,1982],{},"\u002F\u002F → SQL: SELECT * FROM Users WHERE City = 'HCM' (chỉ lấy data cần)\n",[493,1984,1297,1987,1990,1991,1994,1995,1998,1999,2002,2003,2006],{"color":1985,"icon":1986},"error","i-lucide-alert-octagon",[442,1988,1989],{},"Quy tắc EF Core",": giữ ",[476,1992,1993],{},"IQueryable"," đến cuối cùng (right before ",[476,1996,1997],{},".ToList()\u002F.ToListAsync()","). Đừng ",[476,2000,2001],{},".ToList()"," sớm rồi mới ",[476,2004,2005],{},".Where()"," — sẽ kéo hết về client.",[506,2008,2010],{"id":2009},"_34-deferred-execution","3.4. 🟡 Deferred execution",[493,2012,2013,2023],{"color":949,"icon":268},[431,2014,1297,2015,2018,2019,2022],{},[442,2016,2017],{},"LINQ query KHÔNG chạy ngay"," khi gọi ",[476,2020,2021],{},".Where()\u002F.Select()\u002F.OrderBy()",". Chỉ chạy khi:",[435,2024,2025,2032],{},[438,2026,2027,2028,2031],{},"Iterate (",[476,2029,2030],{},"foreach",").",[438,2033,2034,2035,2038,2039,2038,2042,2038,2045,2038,2048,2038,2051,2054],{},"Gọi terminator: ",[476,2036,2037],{},"ToList()",", ",[476,2040,2041],{},"ToArray()",[476,2043,2044],{},"Count()",[476,2046,2047],{},"First()",[476,2049,2050],{},"Any()",[476,2052,2053],{},"Sum()","...",[524,2056,2058],{"className":526,"code":2057,"language":528,"meta":529,"style":529},"var q = users.Where(u => u.Age > 25);     \u002F\u002F CHƯA chạy\nusers.Add(new(\"Eve\", 50, \"HCM\"));         \u002F\u002F thêm sau\n\nforeach (var u in q) Console.WriteLine(u.Name);\n\u002F\u002F Eve xuất hiện! Vì query chạy lúc foreach.\n",[476,2059,2060,2065,2070,2074,2079],{"__ignoreMap":529},[533,2061,2062],{"class":535,"line":536},[533,2063,2064],{},"var q = users.Where(u => u.Age > 25);     \u002F\u002F CHƯA chạy\n",[533,2066,2067],{"class":535,"line":542},[533,2068,2069],{},"users.Add(new(\"Eve\", 50, \"HCM\"));         \u002F\u002F thêm sau\n",[533,2071,2072],{"class":535,"line":548},[533,2073,564],{"emptyLinePlaceholder":563},[533,2075,2076],{"class":535,"line":554},[533,2077,2078],{},"foreach (var u in q) Console.WriteLine(u.Name);\n",[533,2080,2081],{"class":535,"line":560},[533,2082,2083],{},"\u002F\u002F Eve xuất hiện! Vì query chạy lúc foreach.\n",[431,2085,2086],{},[442,2087,2088],{},"Sai lầm phổ biến — chạy nhiều lần ngầm:",[524,2090,2092],{"className":526,"code":2091,"language":528,"meta":529,"style":529},"var q = dbContext.Users.Where(u => u.Active);\n\nConsole.WriteLine(q.Count());         \u002F\u002F SELECT COUNT(*) FROM Users WHERE Active = 1\nforeach (var u in q) { ... }          \u002F\u002F SELECT * FROM Users WHERE Active = 1 — gọi LẦN 2!\n",[476,2093,2094,2099,2103,2108],{"__ignoreMap":529},[533,2095,2096],{"class":535,"line":536},[533,2097,2098],{},"var q = dbContext.Users.Where(u => u.Active);\n",[533,2100,2101],{"class":535,"line":542},[533,2102,564],{"emptyLinePlaceholder":563},[533,2104,2105],{"class":535,"line":548},[533,2106,2107],{},"Console.WriteLine(q.Count());         \u002F\u002F SELECT COUNT(*) FROM Users WHERE Active = 1\n",[533,2109,2110],{"class":535,"line":554},[533,2111,2112],{},"foreach (var u in q) { ... }          \u002F\u002F SELECT * FROM Users WHERE Active = 1 — gọi LẦN 2!\n",[431,2114,2115,2116,2119],{},"→ Fix: ",[476,2117,2118],{},"var list = q.ToList();"," để materialize 1 lần, sau đó iterate nhiều lần OK.",[506,2121,2123,2124,2127],{"id":2122},"_35-cơ-chế-bên-trong-where-thực-sự-làm-gì","3.5. Cơ chế bên trong — ",[476,2125,2126],{},"Where"," thực sự làm gì?",[524,2129,2131],{"className":526,"code":2130,"language":528,"meta":529,"style":529},"public static IEnumerable\u003CT> Where\u003CT>(this IEnumerable\u003CT> src, Func\u003CT, bool> pred) {\n    foreach (var item in src) {\n        if (pred(item)) yield return item;\n    }\n}\n",[476,2132,2133,2138,2143,2148,2152],{"__ignoreMap":529},[533,2134,2135],{"class":535,"line":536},[533,2136,2137],{},"public static IEnumerable\u003CT> Where\u003CT>(this IEnumerable\u003CT> src, Func\u003CT, bool> pred) {\n",[533,2139,2140],{"class":535,"line":542},[533,2141,2142],{},"    foreach (var item in src) {\n",[533,2144,2145],{"class":535,"line":548},[533,2146,2147],{},"        if (pred(item)) yield return item;\n",[533,2149,2150],{"class":535,"line":554},[533,2151,1441],{},[533,2153,2154],{"class":535,"line":560},[533,2155,730],{},[431,2157,2158,2159,2162,2163,2165],{},"→ ",[442,2160,2161],{},"Generator"," dùng ",[476,2164,1415],{},". Không tạo list mới — chỉ wrap source + filter on-demand.",[431,2167,2168,2171],{},[442,2169,2170],{},"Chain method"," = wrap nhiều generator:",[524,2173,2175],{"className":526,"code":2174,"language":528,"meta":529,"style":529},"src.Where(...).Select(...).Take(5)\n\u002F\u002F = Where wraps src\n\u002F\u002F = Select wraps Where\n\u002F\u002F = Take wraps Select\n\u002F\u002F Khi enumerate Take → pull 1 phần tử qua Select → qua Where → từ src\n",[476,2176,2177,2182,2187,2192,2197],{"__ignoreMap":529},[533,2178,2179],{"class":535,"line":536},[533,2180,2181],{},"src.Where(...).Select(...).Take(5)\n",[533,2183,2184],{"class":535,"line":542},[533,2185,2186],{},"\u002F\u002F = Where wraps src\n",[533,2188,2189],{"class":535,"line":548},[533,2190,2191],{},"\u002F\u002F = Select wraps Where\n",[533,2193,2194],{"class":535,"line":554},[533,2195,2196],{},"\u002F\u002F = Take wraps Select\n",[533,2198,2199],{"class":535,"line":560},[533,2200,2201],{},"\u002F\u002F Khi enumerate Take → pull 1 phần tử qua Select → qua Where → từ src\n",[431,2203,2204],{},"Đó là vì sao chain dài LINQ vẫn nhanh — không tạo list trung gian.",[499,2206],{},[426,2208,2210],{"id":2209},"_4-delegate-action-func-event-lambda","4. Delegate, Action, Func, Event, Lambda",[506,2212,2214],{"id":2213},"_41-delegate-function-pointer-type-safe","4.1. Delegate — function pointer type-safe",[493,2216,1540,2217,2220,2221,2031],{"color":495,"icon":496},[442,2218,2219],{},"Delegate"," = biến giữ tham chiếu tới method có signature khớp. Tương đương \"function pointer\" của C\u002FC++ nhưng type-safe và có thể giữ method instance (kèm ",[476,2222,2223],{},"this",[524,2225,2227],{"className":526,"code":2226,"language":528,"meta":529,"style":529},"\u002F\u002F Định nghĩa delegate type\npublic delegate int MathOp(int a, int b);\n\n\u002F\u002F Tạo instance\nMathOp add = (a, b) => a + b;\nMathOp sub = (a, b) => a - b;\n\n\u002F\u002F Gọi như method\nConsole.WriteLine(add(2, 3));    \u002F\u002F 5\nConsole.WriteLine(sub(5, 2));    \u002F\u002F 3\n\n\u002F\u002F Truyền delegate vào method khác\nint Apply(MathOp op, int x, int y) => op(x, y);\nApply(add, 10, 20);              \u002F\u002F 30\n",[476,2228,2229,2234,2239,2243,2248,2253,2258,2262,2267,2272,2277,2281,2286,2291],{"__ignoreMap":529},[533,2230,2231],{"class":535,"line":536},[533,2232,2233],{},"\u002F\u002F Định nghĩa delegate type\n",[533,2235,2236],{"class":535,"line":542},[533,2237,2238],{},"public delegate int MathOp(int a, int b);\n",[533,2240,2241],{"class":535,"line":548},[533,2242,564],{"emptyLinePlaceholder":563},[533,2244,2245],{"class":535,"line":554},[533,2246,2247],{},"\u002F\u002F Tạo instance\n",[533,2249,2250],{"class":535,"line":560},[533,2251,2252],{},"MathOp add = (a, b) => a + b;\n",[533,2254,2255],{"class":535,"line":567},[533,2256,2257],{},"MathOp sub = (a, b) => a - b;\n",[533,2259,2260],{"class":535,"line":573},[533,2261,564],{"emptyLinePlaceholder":563},[533,2263,2264],{"class":535,"line":579},[533,2265,2266],{},"\u002F\u002F Gọi như method\n",[533,2268,2269],{"class":535,"line":709},[533,2270,2271],{},"Console.WriteLine(add(2, 3));    \u002F\u002F 5\n",[533,2273,2274],{"class":535,"line":715},[533,2275,2276],{},"Console.WriteLine(sub(5, 2));    \u002F\u002F 3\n",[533,2278,2279],{"class":535,"line":721},[533,2280,564],{"emptyLinePlaceholder":563},[533,2282,2283],{"class":535,"line":727},[533,2284,2285],{},"\u002F\u002F Truyền delegate vào method khác\n",[533,2287,2288],{"class":535,"line":733},[533,2289,2290],{},"int Apply(MathOp op, int x, int y) => op(x, y);\n",[533,2292,2293],{"class":535,"line":738},[533,2294,2295],{},"Apply(add, 10, 20);              \u002F\u002F 30\n",[506,2297,2299,2300,2038,2303,2038,2306,2309],{"id":2298},"_42-action-func-predicate-built-in-delegate","4.2. ",[476,2301,2302],{},"Action",[476,2304,2305],{},"Func",[476,2307,2308],{},"Predicate"," — built-in delegate",[431,2311,2312,2313,522],{},"C# có sẵn delegate generic — ",[442,2314,2315],{},"không cần tự định nghĩa",[790,2317,2318,2330],{},[793,2319,2320],{},[796,2321,2322,2324,2327],{},[799,2323,2219],{},[799,2325,2326],{},"Signature",[799,2328,2329],{},"Khi dùng",[806,2331,2332,2346,2361,2376,2391,2406,2424],{},[796,2333,2334,2338,2343],{},[811,2335,2336],{},[476,2337,2302],{},[811,2339,2340],{},[476,2341,2342],{},"void()",[811,2344,2345],{},"Không tham số, không return",[796,2347,2348,2353,2358],{},[811,2349,2350],{},[476,2351,2352],{},"Action\u003CT>",[811,2354,2355],{},[476,2356,2357],{},"void(T)",[811,2359,2360],{},"1 tham số, không return",[796,2362,2363,2368,2373],{},[811,2364,2365],{},[476,2366,2367],{},"Action\u003CT1, T2>",[811,2369,2370],{},[476,2371,2372],{},"void(T1, T2)",[811,2374,2375],{},"2 tham số, không return",[796,2377,2378,2383,2388],{},[811,2379,2380],{},[476,2381,2382],{},"Func\u003CTResult>",[811,2384,2385],{},[476,2386,2387],{},"TResult()",[811,2389,2390],{},"Không tham số, có return",[796,2392,2393,2398,2403],{},[811,2394,2395],{},[476,2396,2397],{},"Func\u003CT, TResult>",[811,2399,2400],{},[476,2401,2402],{},"TResult(T)",[811,2404,2405],{},"1 tham số, có return",[796,2407,2408,2413,2418],{},[811,2409,2410],{},[476,2411,2412],{},"Func\u003CT, bool>",[811,2414,2415],{},[476,2416,2417],{},"bool(T)",[811,2419,2420,2421],{},"= ",[476,2422,2423],{},"Predicate\u003CT>",[796,2425,2426,2430,2434],{},[811,2427,2428],{},[476,2429,2423],{},[811,2431,2432],{},[476,2433,2417],{},[811,2435,2436],{},"(legacy, ít dùng)",[524,2438,2440],{"className":526,"code":2439,"language":528,"meta":529,"style":529},"Action\u003Cstring> log = msg => Console.WriteLine(msg);\nFunc\u003Cint, int, int> mul = (a, b) => a * b;\nFunc\u003Cstring, bool> isEmpty = s => string.IsNullOrEmpty(s);\n\n\u002F\u002F Truyền vào LINQ\nvar names = users.Select((Func\u003CUser, string>)(u => u.Name));    \u002F\u002F hiếm khi cần cast — tự inferred\n",[476,2441,2442,2447,2452,2457,2461,2466],{"__ignoreMap":529},[533,2443,2444],{"class":535,"line":536},[533,2445,2446],{},"Action\u003Cstring> log = msg => Console.WriteLine(msg);\n",[533,2448,2449],{"class":535,"line":542},[533,2450,2451],{},"Func\u003Cint, int, int> mul = (a, b) => a * b;\n",[533,2453,2454],{"class":535,"line":548},[533,2455,2456],{},"Func\u003Cstring, bool> isEmpty = s => string.IsNullOrEmpty(s);\n",[533,2458,2459],{"class":535,"line":554},[533,2460,564],{"emptyLinePlaceholder":563},[533,2462,2463],{"class":535,"line":560},[533,2464,2465],{},"\u002F\u002F Truyền vào LINQ\n",[533,2467,2468],{"class":535,"line":567},[533,2469,2470],{},"var names = users.Select((Func\u003CUser, string>)(u => u.Name));    \u002F\u002F hiếm khi cần cast — tự inferred\n",[506,2472,2474],{"id":2473},"_43-lambda-cú-pháp-inline","4.3. Lambda — cú pháp inline",[524,2476,2478],{"className":526,"code":2477,"language":528,"meta":529,"style":529},"\u002F\u002F Lambda expression — 1 expression\nFunc\u003Cint, int> sq = x => x * x;\n\n\u002F\u002F Lambda statement — nhiều dòng, dùng {}\nFunc\u003Cint, int> abs = x => {\n    if (x \u003C 0) return -x;\n    return x;\n};\n\n\u002F\u002F Không tham số\nAction greet = () => Console.WriteLine(\"Hi\");\n\n\u002F\u002F Nhiều tham số\nFunc\u003Cint, int, int> add = (a, b) => a + b;\n\n\u002F\u002F Type explicit (đôi khi cần)\nFunc\u003Cint, int> doubled = (int x) => x * 2;\n",[476,2479,2480,2485,2490,2494,2499,2504,2509,2514,2518,2522,2527,2532,2536,2541,2546,2550,2555],{"__ignoreMap":529},[533,2481,2482],{"class":535,"line":536},[533,2483,2484],{},"\u002F\u002F Lambda expression — 1 expression\n",[533,2486,2487],{"class":535,"line":542},[533,2488,2489],{},"Func\u003Cint, int> sq = x => x * x;\n",[533,2491,2492],{"class":535,"line":548},[533,2493,564],{"emptyLinePlaceholder":563},[533,2495,2496],{"class":535,"line":554},[533,2497,2498],{},"\u002F\u002F Lambda statement — nhiều dòng, dùng {}\n",[533,2500,2501],{"class":535,"line":560},[533,2502,2503],{},"Func\u003Cint, int> abs = x => {\n",[533,2505,2506],{"class":535,"line":567},[533,2507,2508],{},"    if (x \u003C 0) return -x;\n",[533,2510,2511],{"class":535,"line":573},[533,2512,2513],{},"    return x;\n",[533,2515,2516],{"class":535,"line":579},[533,2517,1641],{},[533,2519,2520],{"class":535,"line":709},[533,2521,564],{"emptyLinePlaceholder":563},[533,2523,2524],{"class":535,"line":715},[533,2525,2526],{},"\u002F\u002F Không tham số\n",[533,2528,2529],{"class":535,"line":721},[533,2530,2531],{},"Action greet = () => Console.WriteLine(\"Hi\");\n",[533,2533,2534],{"class":535,"line":727},[533,2535,564],{"emptyLinePlaceholder":563},[533,2537,2538],{"class":535,"line":733},[533,2539,2540],{},"\u002F\u002F Nhiều tham số\n",[533,2542,2543],{"class":535,"line":738},[533,2544,2545],{},"Func\u003Cint, int, int> add = (a, b) => a + b;\n",[533,2547,2548],{"class":535,"line":744},[533,2549,564],{"emptyLinePlaceholder":563},[533,2551,2552],{"class":535,"line":750},[533,2553,2554],{},"\u002F\u002F Type explicit (đôi khi cần)\n",[533,2556,2557],{"class":535,"line":755},[533,2558,2559],{},"Func\u003Cint, int> doubled = (int x) => x * 2;\n",[506,2561,2563],{"id":2562},"_44-closure-bắt-biến-từ-scope-ngoài","4.4. 🟡 Closure — bắt biến từ scope ngoài",[524,2565,2567],{"className":526,"code":2566,"language":528,"meta":529,"style":529},"int multiplier = 3;\nFunc\u003Cint, int> times = x => x * multiplier;    \u002F\u002F bắt `multiplier`\n\nmultiplier = 10;\nConsole.WriteLine(times(5));    \u002F\u002F 50 — đọc giá trị MỚI của multiplier!\n",[476,2568,2569,2574,2579,2583,2588],{"__ignoreMap":529},[533,2570,2571],{"class":535,"line":536},[533,2572,2573],{},"int multiplier = 3;\n",[533,2575,2576],{"class":535,"line":542},[533,2577,2578],{},"Func\u003Cint, int> times = x => x * multiplier;    \u002F\u002F bắt `multiplier`\n",[533,2580,2581],{"class":535,"line":548},[533,2582,564],{"emptyLinePlaceholder":563},[533,2584,2585],{"class":535,"line":554},[533,2586,2587],{},"multiplier = 10;\n",[533,2589,2590],{"class":535,"line":560},[533,2591,2592],{},"Console.WriteLine(times(5));    \u002F\u002F 50 — đọc giá trị MỚI của multiplier!\n",[493,2594,2595,2601,2630,2640],{"color":949,"icon":268},[431,2596,1297,2597,2600],{},[442,2598,2599],{},"Closure thực sự bắt VARIABLE, không phải VALUE."," Compiler tạo class ẩn chứa biến bắt được. Lambda là method của class này.",[524,2602,2604],{"className":526,"code":2603,"language":528,"meta":529,"style":529},"\u002F\u002F Compiler sinh:\nclass __Closure {\n    public int multiplier;\n    public int Lambda(int x) => x * multiplier;\n}\n",[476,2605,2606,2611,2616,2621,2626],{"__ignoreMap":529},[533,2607,2608],{"class":535,"line":536},[533,2609,2610],{},"\u002F\u002F Compiler sinh:\n",[533,2612,2613],{"class":535,"line":542},[533,2614,2615],{},"class __Closure {\n",[533,2617,2618],{"class":535,"line":548},[533,2619,2620],{},"    public int multiplier;\n",[533,2622,2623],{"class":535,"line":554},[533,2624,2625],{},"    public int Lambda(int x) => x * multiplier;\n",[533,2627,2628],{"class":535,"line":560},[533,2629,730],{},[431,2631,2632,2633,2635,2636,2639],{},"→ Có thể gây bug khi lambda capture biến vòng lặp (C# 5+ đã fix ",[476,2634,2030],{},", nhưng ",[476,2637,2638],{},"for"," vẫn cẩn thận):",[524,2641,2643],{"className":526,"code":2642,"language":528,"meta":529,"style":529},"var actions = new List\u003CAction>();\nfor (int i = 0; i \u003C 3; i++) {\n    actions.Add(() => Console.WriteLine(i));    \u002F\u002F bắt i!\n}\nforeach (var a in actions) a();\n\u002F\u002F Output: 3, 3, 3 — i = 3 khi loop kết thúc!\n\n\u002F\u002F Fix: tạo biến local trong loop\nfor (int i = 0; i \u003C 3; i++) {\n    int local = i;\n    actions.Add(() => Console.WriteLine(local));    \u002F\u002F bắt local — khác biến mỗi vòng\n}\n\u002F\u002F Output: 0, 1, 2 ✅\n",[476,2644,2645,2650,2655,2660,2664,2669,2674,2678,2683,2687,2692,2697,2701],{"__ignoreMap":529},[533,2646,2647],{"class":535,"line":536},[533,2648,2649],{},"var actions = new List\u003CAction>();\n",[533,2651,2652],{"class":535,"line":542},[533,2653,2654],{},"for (int i = 0; i \u003C 3; i++) {\n",[533,2656,2657],{"class":535,"line":548},[533,2658,2659],{},"    actions.Add(() => Console.WriteLine(i));    \u002F\u002F bắt i!\n",[533,2661,2662],{"class":535,"line":554},[533,2663,730],{},[533,2665,2666],{"class":535,"line":560},[533,2667,2668],{},"foreach (var a in actions) a();\n",[533,2670,2671],{"class":535,"line":567},[533,2672,2673],{},"\u002F\u002F Output: 3, 3, 3 — i = 3 khi loop kết thúc!\n",[533,2675,2676],{"class":535,"line":573},[533,2677,564],{"emptyLinePlaceholder":563},[533,2679,2680],{"class":535,"line":579},[533,2681,2682],{},"\u002F\u002F Fix: tạo biến local trong loop\n",[533,2684,2685],{"class":535,"line":709},[533,2686,2654],{},[533,2688,2689],{"class":535,"line":715},[533,2690,2691],{},"    int local = i;\n",[533,2693,2694],{"class":535,"line":721},[533,2695,2696],{},"    actions.Add(() => Console.WriteLine(local));    \u002F\u002F bắt local — khác biến mỗi vòng\n",[533,2698,2699],{"class":535,"line":727},[533,2700,730],{},[533,2702,2703],{"class":535,"line":733},[533,2704,2705],{},"\u002F\u002F Output: 0, 1, 2 ✅\n",[506,2707,2709],{"id":2708},"_45-event-observer-pattern-built-in","4.5. Event — Observer pattern built-in",[524,2711,2713],{"className":526,"code":2712,"language":528,"meta":529,"style":529},"public class StockTicker {\n    \u002F\u002F Event = delegate được wrap để class ngoài chỉ += \u002F -=, không Invoke\n    public event EventHandler\u003CPriceChangedEventArgs>? PriceChanged;\n    \n    public void UpdatePrice(string symbol, decimal newPrice) {\n        \u002F\u002F Class chủ tự fire event\n        PriceChanged?.Invoke(this, new PriceChangedEventArgs(symbol, newPrice));\n    }\n}\n\npublic class PriceChangedEventArgs : EventArgs {\n    public string Symbol { get; }\n    public decimal NewPrice { get; }\n    public PriceChangedEventArgs(string s, decimal p) { Symbol = s; NewPrice = p; }\n}\n\n\u002F\u002F Subscribe\nvar ticker = new StockTicker();\nticker.PriceChanged += (sender, e) => Console.WriteLine($\"{e.Symbol}: {e.NewPrice}\");\nticker.PriceChanged += SaveToDatabase;       \u002F\u002F method reference\n\nticker.UpdatePrice(\"AAPL\", 150.5m);\n\u002F\u002F 2 subscriber chạy lần lượt\n",[476,2714,2715,2720,2725,2730,2735,2740,2745,2750,2754,2758,2762,2767,2772,2777,2782,2786,2790,2795,2800,2805,2810,2814,2819],{"__ignoreMap":529},[533,2716,2717],{"class":535,"line":536},[533,2718,2719],{},"public class StockTicker {\n",[533,2721,2722],{"class":535,"line":542},[533,2723,2724],{},"    \u002F\u002F Event = delegate được wrap để class ngoài chỉ += \u002F -=, không Invoke\n",[533,2726,2727],{"class":535,"line":548},[533,2728,2729],{},"    public event EventHandler\u003CPriceChangedEventArgs>? PriceChanged;\n",[533,2731,2732],{"class":535,"line":554},[533,2733,2734],{},"    \n",[533,2736,2737],{"class":535,"line":560},[533,2738,2739],{},"    public void UpdatePrice(string symbol, decimal newPrice) {\n",[533,2741,2742],{"class":535,"line":567},[533,2743,2744],{},"        \u002F\u002F Class chủ tự fire event\n",[533,2746,2747],{"class":535,"line":573},[533,2748,2749],{},"        PriceChanged?.Invoke(this, new PriceChangedEventArgs(symbol, newPrice));\n",[533,2751,2752],{"class":535,"line":579},[533,2753,1441],{},[533,2755,2756],{"class":535,"line":709},[533,2757,730],{},[533,2759,2760],{"class":535,"line":715},[533,2761,564],{"emptyLinePlaceholder":563},[533,2763,2764],{"class":535,"line":721},[533,2765,2766],{},"public class PriceChangedEventArgs : EventArgs {\n",[533,2768,2769],{"class":535,"line":727},[533,2770,2771],{},"    public string Symbol { get; }\n",[533,2773,2774],{"class":535,"line":733},[533,2775,2776],{},"    public decimal NewPrice { get; }\n",[533,2778,2779],{"class":535,"line":738},[533,2780,2781],{},"    public PriceChangedEventArgs(string s, decimal p) { Symbol = s; NewPrice = p; }\n",[533,2783,2784],{"class":535,"line":744},[533,2785,730],{},[533,2787,2788],{"class":535,"line":750},[533,2789,564],{"emptyLinePlaceholder":563},[533,2791,2792],{"class":535,"line":755},[533,2793,2794],{},"\u002F\u002F Subscribe\n",[533,2796,2797],{"class":535,"line":761},[533,2798,2799],{},"var ticker = new StockTicker();\n",[533,2801,2802],{"class":535,"line":767},[533,2803,2804],{},"ticker.PriceChanged += (sender, e) => Console.WriteLine($\"{e.Symbol}: {e.NewPrice}\");\n",[533,2806,2807],{"class":535,"line":773},[533,2808,2809],{},"ticker.PriceChanged += SaveToDatabase;       \u002F\u002F method reference\n",[533,2811,2812],{"class":535,"line":779},[533,2813,564],{"emptyLinePlaceholder":563},[533,2815,2816],{"class":535,"line":1719},[533,2817,2818],{},"ticker.UpdatePrice(\"AAPL\", 150.5m);\n",[533,2820,2821],{"class":535,"line":1725},[533,2822,2823],{},"\u002F\u002F 2 subscriber chạy lần lượt\n",[506,2825,2827],{"id":2826},"_46-event-vs-delegate-public","4.6. 🟡 Event vs Delegate public",[493,2829,2830,2840,2843,2852,2855,2873],{"color":949,"icon":1857},[431,2831,1860,2832,2835,2836],{},[442,2833,2834],{},"Câu PV:"," ",[2837,2838,2839],"em",{},"\"Vì sao event tốt hơn delegate public?\"",[431,2841,2842],{},"Nếu delegate là public field:",[524,2844,2846],{"className":526,"code":2845,"language":528,"meta":529,"style":529},"public Action\u003Cstring>? PriceChanged;   \u002F\u002F PUBLIC delegate\n",[476,2847,2848],{"__ignoreMap":529},[533,2849,2850],{"class":535,"line":536},[533,2851,2845],{},[431,2853,2854],{},"Class ngoài có thể:",[435,2856,2857,2865],{},[438,2858,2859,1005,2862,1396],{},[476,2860,2861],{},"ticker.PriceChanged = null;",[442,2863,2864],{},"xoá hết subscriber khác",[438,2866,2867,1005,2870,1396],{},[476,2868,2869],{},"ticker.PriceChanged.Invoke(...);",[442,2871,2872],{},"fire event giả mạo",[431,2874,2875,2878,2879,2882,2883,2886],{},[476,2876,2877],{},"event"," keyword wrap delegate, chỉ cho phép ",[476,2880,2881],{},"+="," \u002F ",[476,2884,2885],{},"-="," từ ngoài. Invoke + Reset chỉ class chủ làm được.",[499,2888],{},[426,2890,2892],{"id":2891},"_5-extension-method","5. Extension method",[506,2894,2896],{"id":2895},"_51-cú-pháp","5.1. Cú pháp",[524,2898,2900],{"className":526,"code":2899,"language":528,"meta":529,"style":529},"public static class StringExtensions {\n    public static bool IsValidEmail(this string s) {\n        return s.Contains('@') && s.Contains('.');\n    }\n    \n    public static string Repeat(this string s, int times) {\n        return string.Concat(Enumerable.Repeat(s, times));\n    }\n}\n\n\u002F\u002F Dùng như method của string\n\"a@b.com\".IsValidEmail();    \u002F\u002F true\n\"Ha\".Repeat(3);              \u002F\u002F \"HaHaHa\"\n",[476,2901,2902,2907,2912,2917,2921,2925,2930,2935,2939,2943,2947,2952,2960],{"__ignoreMap":529},[533,2903,2904],{"class":535,"line":536},[533,2905,2906],{},"public static class StringExtensions {\n",[533,2908,2909],{"class":535,"line":542},[533,2910,2911],{},"    public static bool IsValidEmail(this string s) {\n",[533,2913,2914],{"class":535,"line":548},[533,2915,2916],{},"        return s.Contains('@') && s.Contains('.');\n",[533,2918,2919],{"class":535,"line":554},[533,2920,1441],{},[533,2922,2923],{"class":535,"line":560},[533,2924,2734],{},[533,2926,2927],{"class":535,"line":567},[533,2928,2929],{},"    public static string Repeat(this string s, int times) {\n",[533,2931,2932],{"class":535,"line":573},[533,2933,2934],{},"        return string.Concat(Enumerable.Repeat(s, times));\n",[533,2936,2937],{"class":535,"line":579},[533,2938,1441],{},[533,2940,2941],{"class":535,"line":709},[533,2942,730],{},[533,2944,2945],{"class":535,"line":715},[533,2946,564],{"emptyLinePlaceholder":563},[533,2948,2949],{"class":535,"line":721},[533,2950,2951],{},"\u002F\u002F Dùng như method của string\n",[533,2953,2954,2957],{"class":535,"line":727},[533,2955,2956],{},"\"a@b.com\".IsValidEmail();",[533,2958,2959],{},"    \u002F\u002F true\n",[533,2961,2962,2965],{"class":535,"line":733},[533,2963,2964],{},"\"Ha\".Repeat(3);",[533,2966,2967],{},"              \u002F\u002F \"HaHaHa\"\n",[431,2969,2970],{},[442,2971,2972],{},"Quy tắc:",[435,2974,2975,2978,2981],{},[438,2976,2977],{},"Static class.",[438,2979,2980],{},"Static method.",[438,2982,2983,2984,2986],{},"Tham số đầu có ",[476,2985,2223],{}," modifier.",[506,2988,2990],{"id":2989},"_52-bên-trong-chỉ-là-syntactic-sugar","5.2. Bên trong — chỉ là syntactic sugar",[431,2992,2993],{},"Compiler dịch:",[524,2995,2997],{"className":526,"code":2996,"language":528,"meta":529,"style":529},"\"hi\".Repeat(3)\n\u002F\u002F thành:\nStringExtensions.Repeat(\"hi\", 3)\n",[476,2998,2999,3004,3009],{"__ignoreMap":529},[533,3000,3001],{"class":535,"line":536},[533,3002,3003],{},"\"hi\".Repeat(3)\n",[533,3005,3006],{"class":535,"line":542},[533,3007,3008],{},"\u002F\u002F thành:\n",[533,3010,3011],{"class":535,"line":548},[533,3012,3013],{},"StringExtensions.Repeat(\"hi\", 3)\n",[431,3015,3016],{},"Không có magic — chỉ là syntactic sugar.",[506,3018,3020],{"id":3019},"_53-linq-chính-là-extension-method","5.3. LINQ chính là extension method",[524,3022,3024],{"className":526,"code":3023,"language":528,"meta":529,"style":529},"namespace System.Linq {\n    public static class Enumerable {\n        public static IEnumerable\u003CT> Where\u003CT>(this IEnumerable\u003CT> src, Func\u003CT, bool> pred) {...}\n        public static IEnumerable\u003CU> Select\u003CT, U>(this IEnumerable\u003CT> src, Func\u003CT, U> sel) {...}\n        \u002F\u002F ...\n    }\n}\n",[476,3025,3026,3031,3036,3041,3046,3051,3055],{"__ignoreMap":529},[533,3027,3028],{"class":535,"line":536},[533,3029,3030],{},"namespace System.Linq {\n",[533,3032,3033],{"class":535,"line":542},[533,3034,3035],{},"    public static class Enumerable {\n",[533,3037,3038],{"class":535,"line":548},[533,3039,3040],{},"        public static IEnumerable\u003CT> Where\u003CT>(this IEnumerable\u003CT> src, Func\u003CT, bool> pred) {...}\n",[533,3042,3043],{"class":535,"line":554},[533,3044,3045],{},"        public static IEnumerable\u003CU> Select\u003CT, U>(this IEnumerable\u003CT> src, Func\u003CT, U> sel) {...}\n",[533,3047,3048],{"class":535,"line":560},[533,3049,3050],{},"        \u002F\u002F ...\n",[533,3052,3053],{"class":535,"line":567},[533,3054,1441],{},[533,3056,3057],{"class":535,"line":573},[533,3058,730],{},[431,3060,3061,3062,3064,3065,3068,3069,3071],{},"→ Mọi ",[476,3063,1384],{}," có Where\u002FSelect\u002Fetc. ",[442,3066,3067],{},"bất kỳ collection"," nào implement ",[476,3070,1384],{}," đều dùng LINQ được — power lớn.",[499,3073],{},[426,3075,3077],{"id":3076},"_6-async-await-hiểu-đúng","6. async \u002F await — hiểu ĐÚNG",[506,3079,3081],{"id":3080},"_61-câu-hỏi-gài-asyncawait-có-tạo-thread-mới-không","6.1. Câu hỏi gài: \"async\u002Fawait có tạo thread mới không?\"",[493,3083,1860,3084,2835,3087,2835,3090,2835,3092,1396],{"color":949,"icon":1857},[442,3085,3086],{},"Đáp:",[442,3088,3089],{},"KHÔNG.",[476,3091,478],{},[442,3093,3094],{},"không tạo thread mới",[506,3096,3098],{"id":3097},"_62-cơ-chế-thực-sự-state-machine","6.2. Cơ chế thực sự — state machine",[524,3100,3102],{"className":526,"code":3101,"language":528,"meta":529,"style":529},"public async Task\u003Cstring> GetUserAsync(int id) {\n    var http = new HttpClient();\n    var json = await http.GetStringAsync($\"\u002Fapi\u002Fusers\u002F{id}\");\n    return json;\n}\n",[476,3103,3104,3109,3114,3119,3124],{"__ignoreMap":529},[533,3105,3106],{"class":535,"line":536},[533,3107,3108],{},"public async Task\u003Cstring> GetUserAsync(int id) {\n",[533,3110,3111],{"class":535,"line":542},[533,3112,3113],{},"    var http = new HttpClient();\n",[533,3115,3116],{"class":535,"line":548},[533,3117,3118],{},"    var json = await http.GetStringAsync($\"\u002Fapi\u002Fusers\u002F{id}\");\n",[533,3120,3121],{"class":535,"line":554},[533,3122,3123],{},"    return json;\n",[533,3125,3126],{"class":535,"line":560},[533,3127,730],{},[431,3129,3130],{},"Compiler dịch thành class state machine (giản lược):",[524,3132,3134],{"className":526,"code":3133,"language":528,"meta":529,"style":529},"public Task\u003Cstring> GetUserAsync(int id) {\n    var sm = new GetUserStateMachine {\n        id = id,\n        state = -1\n    };\n    sm.MoveNext();     \u002F\u002F start\n    return sm.Task;\n}\n\nclass GetUserStateMachine : IAsyncStateMachine {\n    public int state;\n    public int id;\n    public TaskCompletionSource\u003Cstring> Task;\n    public HttpClient http;\n    public TaskAwaiter\u003Cstring> awaiter;\n    \n    public void MoveNext() {\n        switch (state) {\n            case -1:\n                http = new HttpClient();\n                var task = http.GetStringAsync($\"\u002Fapi\u002Fusers\u002F{id}\");\n                awaiter = task.GetAwaiter();\n                if (!awaiter.IsCompleted) {\n                    state = 0;\n                    awaiter.OnCompleted(MoveNext);    \u002F\u002F schedule callback, return!\n                    return;\n                }\n                goto case 0;\n                \n            case 0:\n                string json = awaiter.GetResult();\n                Task.SetResult(json);\n                return;\n        }\n    }\n}\n",[476,3135,3136,3141,3146,3151,3156,3161,3166,3171,3175,3179,3184,3189,3194,3199,3204,3209,3213,3218,3223,3228,3233,3238,3243,3248,3253,3258,3263,3268,3273,3278,3283,3288,3293,3298,3303,3307],{"__ignoreMap":529},[533,3137,3138],{"class":535,"line":536},[533,3139,3140],{},"public Task\u003Cstring> GetUserAsync(int id) {\n",[533,3142,3143],{"class":535,"line":542},[533,3144,3145],{},"    var sm = new GetUserStateMachine {\n",[533,3147,3148],{"class":535,"line":548},[533,3149,3150],{},"        id = id,\n",[533,3152,3153],{"class":535,"line":554},[533,3154,3155],{},"        state = -1\n",[533,3157,3158],{"class":535,"line":560},[533,3159,3160],{},"    };\n",[533,3162,3163],{"class":535,"line":567},[533,3164,3165],{},"    sm.MoveNext();     \u002F\u002F start\n",[533,3167,3168],{"class":535,"line":573},[533,3169,3170],{},"    return sm.Task;\n",[533,3172,3173],{"class":535,"line":579},[533,3174,730],{},[533,3176,3177],{"class":535,"line":709},[533,3178,564],{"emptyLinePlaceholder":563},[533,3180,3181],{"class":535,"line":715},[533,3182,3183],{},"class GetUserStateMachine : IAsyncStateMachine {\n",[533,3185,3186],{"class":535,"line":721},[533,3187,3188],{},"    public int state;\n",[533,3190,3191],{"class":535,"line":727},[533,3192,3193],{},"    public int id;\n",[533,3195,3196],{"class":535,"line":733},[533,3197,3198],{},"    public TaskCompletionSource\u003Cstring> Task;\n",[533,3200,3201],{"class":535,"line":738},[533,3202,3203],{},"    public HttpClient http;\n",[533,3205,3206],{"class":535,"line":744},[533,3207,3208],{},"    public TaskAwaiter\u003Cstring> awaiter;\n",[533,3210,3211],{"class":535,"line":750},[533,3212,2734],{},[533,3214,3215],{"class":535,"line":755},[533,3216,3217],{},"    public void MoveNext() {\n",[533,3219,3220],{"class":535,"line":761},[533,3221,3222],{},"        switch (state) {\n",[533,3224,3225],{"class":535,"line":767},[533,3226,3227],{},"            case -1:\n",[533,3229,3230],{"class":535,"line":773},[533,3231,3232],{},"                http = new HttpClient();\n",[533,3234,3235],{"class":535,"line":779},[533,3236,3237],{},"                var task = http.GetStringAsync($\"\u002Fapi\u002Fusers\u002F{id}\");\n",[533,3239,3240],{"class":535,"line":1719},[533,3241,3242],{},"                awaiter = task.GetAwaiter();\n",[533,3244,3245],{"class":535,"line":1725},[533,3246,3247],{},"                if (!awaiter.IsCompleted) {\n",[533,3249,3250],{"class":535,"line":1731},[533,3251,3252],{},"                    state = 0;\n",[533,3254,3255],{"class":535,"line":1737},[533,3256,3257],{},"                    awaiter.OnCompleted(MoveNext);    \u002F\u002F schedule callback, return!\n",[533,3259,3260],{"class":535,"line":1743},[533,3261,3262],{},"                    return;\n",[533,3264,3265],{"class":535,"line":1748},[533,3266,3267],{},"                }\n",[533,3269,3270],{"class":535,"line":1754},[533,3271,3272],{},"                goto case 0;\n",[533,3274,3275],{"class":535,"line":1760},[533,3276,3277],{},"                \n",[533,3279,3280],{"class":535,"line":1766},[533,3281,3282],{},"            case 0:\n",[533,3284,3285],{"class":535,"line":1771},[533,3286,3287],{},"                string json = awaiter.GetResult();\n",[533,3289,3290],{"class":535,"line":1777},[533,3291,3292],{},"                Task.SetResult(json);\n",[533,3294,3295],{"class":535,"line":1783},[533,3296,3297],{},"                return;\n",[533,3299,3300],{"class":535,"line":1789},[533,3301,3302],{},"        }\n",[533,3304,3305],{"class":535,"line":1795},[533,3306,1441],{},[533,3308,3309],{"class":535,"line":1800},[533,3310,730],{},[431,3312,3313],{},[442,3314,3315],{},"Hiểu nôm na:",[587,3317,3318,3329,3332,3335],{},[438,3319,3320,3321,3324,3325,3328],{},"Khi gặp ",[476,3322,3323],{},"await",", method trả ",[476,3326,3327],{},"Task"," ngay → thread caller được giải phóng.",[438,3330,3331],{},"State machine schedule callback chạy khi I\u002FO xong.",[438,3333,3334],{},"Khi I\u002FO xong, callback có thể chạy trên thread khác từ ThreadPool.",[438,3336,3337],{},"State machine resume từ vị trí await, không phải đầu method.",[493,3339,1297,3341,2835,3344],{"color":3340,"icon":268},"success",[442,3342,3343],{},"Tóm tắt cho PV:",[2837,3345,3346,3347,3349,3350,3352],{},"\"",[476,3348,478],{}," không tạo thread mới. Khi gặp ",[476,3351,3323],{},", method giải phóng thread hiện tại, return Task. Khi I\u002FO xong (HTTP\u002FDB response về), runtime schedule continuation chạy trên ThreadPool thread bất kỳ. Mục đích: giải phóng thread trong khi chờ I\u002FO — không phải để parallel.\"",[506,3354,3356],{"id":3355},"_63-khi-nào-dùng-async-io-bound-vs-cpu-bound","6.3. Khi nào dùng async — I\u002FO bound vs CPU bound",[790,3358,3359,3369],{},[793,3360,3361],{},[796,3362,3363,3366],{},[799,3364,3365],{},"Loại work",[799,3367,3368],{},"Dùng gì",[806,3370,3371,3384,3398],{},[796,3372,3373,3379],{},[811,3374,3375,3378],{},[442,3376,3377],{},"I\u002FO bound"," (HTTP, DB, file, network)",[811,3380,3381,3383],{},[476,3382,478],{}," trực tiếp — không cần Task.Run",[796,3385,3386,3392],{},[811,3387,3388,3391],{},[442,3389,3390],{},"CPU bound"," (heavy math, image processing)",[811,3393,3394,3397],{},[476,3395,3396],{},"Task.Run(() => ...)"," để offload sang ThreadPool",[796,3399,3400,3406],{},[811,3401,3402,3405],{},[442,3403,3404],{},"Long-running"," background",[811,3407,3408,2038,3411],{},[476,3409,3410],{},"IHostedService",[476,3412,3413],{},"BackgroundService",[524,3415,3417],{"className":526,"code":3416,"language":528,"meta":529,"style":529},"\u002F\u002F ✅ I\u002FO bound — async trực tiếp\npublic async Task\u003CUser> GetUserAsync(int id) {\n    return await _db.Users.FindAsync(id);\n}\n\n\u002F\u002F ✅ CPU bound — offload\npublic async Task\u003Cint> CalculatePrimesAsync(int limit) {\n    return await Task.Run(() => CountPrimes(limit));    \u002F\u002F CountPrimes nặng CPU\n}\n\n\u002F\u002F ❌ Sai — Task.Run cho I\u002FO work là vô nghĩa\npublic async Task\u003CUser> GetUserBad(int id) {\n    return await Task.Run(() => _db.Users.FindAsync(id));    \u002F\u002F thêm 1 thread vô ích\n}\n",[476,3418,3419,3424,3429,3434,3438,3442,3447,3452,3457,3461,3465,3470,3475,3480],{"__ignoreMap":529},[533,3420,3421],{"class":535,"line":536},[533,3422,3423],{},"\u002F\u002F ✅ I\u002FO bound — async trực tiếp\n",[533,3425,3426],{"class":535,"line":542},[533,3427,3428],{},"public async Task\u003CUser> GetUserAsync(int id) {\n",[533,3430,3431],{"class":535,"line":548},[533,3432,3433],{},"    return await _db.Users.FindAsync(id);\n",[533,3435,3436],{"class":535,"line":554},[533,3437,730],{},[533,3439,3440],{"class":535,"line":560},[533,3441,564],{"emptyLinePlaceholder":563},[533,3443,3444],{"class":535,"line":567},[533,3445,3446],{},"\u002F\u002F ✅ CPU bound — offload\n",[533,3448,3449],{"class":535,"line":573},[533,3450,3451],{},"public async Task\u003Cint> CalculatePrimesAsync(int limit) {\n",[533,3453,3454],{"class":535,"line":579},[533,3455,3456],{},"    return await Task.Run(() => CountPrimes(limit));    \u002F\u002F CountPrimes nặng CPU\n",[533,3458,3459],{"class":535,"line":709},[533,3460,730],{},[533,3462,3463],{"class":535,"line":715},[533,3464,564],{"emptyLinePlaceholder":563},[533,3466,3467],{"class":535,"line":721},[533,3468,3469],{},"\u002F\u002F ❌ Sai — Task.Run cho I\u002FO work là vô nghĩa\n",[533,3471,3472],{"class":535,"line":727},[533,3473,3474],{},"public async Task\u003CUser> GetUserBad(int id) {\n",[533,3476,3477],{"class":535,"line":733},[533,3478,3479],{},"    return await Task.Run(() => _db.Users.FindAsync(id));    \u002F\u002F thêm 1 thread vô ích\n",[533,3481,3482],{"class":535,"line":738},[533,3483,730],{},[506,3485,3487],{"id":3486},"_64-task-vs-thread","6.4. Task vs Thread",[3489,3490,3491,3501,3506],"field-group",{},[3492,3493,3496,3497,3500],"field",{"name":3494,"type":3495},"Thread","OS thread","Heavy. 1 MB stack. Tạo bằng ",[476,3498,3499],{},"new Thread(...)",". Manual lifecycle.",[3492,3502,3505],{"name":3503,"type":3504},"ThreadPool","Pool tái sử dụng","Tránh tạo\u002Fhuỷ thread overhead. CLR quản lý số thread.",[3492,3507,3509,3510],{"name":3327,"type":3508},"Abstraction","Trên ThreadPool. Có Task",[1261,3511,3512,3513,3515],{}," trả value, hỗ trợ continuation (",[476,3514,3323],{},"), cancellation, exception propagation.",[524,3517,3519],{"className":526,"code":3518,"language":528,"meta":529,"style":529},"\u002F\u002F Thread thủ công — hiếm dùng\nvar t = new Thread(() => HeavyWork());\nt.Start();\nt.Join();    \u002F\u002F chờ xong\n\n\u002F\u002F Task — chuẩn hiện đại\nvar task = Task.Run(() => HeavyWork());\nawait task;\n\n\u002F\u002F Multiple parallel\nvar tasks = users.Select(u => FetchOrdersAsync(u.Id)).ToList();\nawait Task.WhenAll(tasks);\n",[476,3520,3521,3526,3531,3536,3541,3545,3550,3555,3560,3564,3569,3574],{"__ignoreMap":529},[533,3522,3523],{"class":535,"line":536},[533,3524,3525],{},"\u002F\u002F Thread thủ công — hiếm dùng\n",[533,3527,3528],{"class":535,"line":542},[533,3529,3530],{},"var t = new Thread(() => HeavyWork());\n",[533,3532,3533],{"class":535,"line":548},[533,3534,3535],{},"t.Start();\n",[533,3537,3538],{"class":535,"line":554},[533,3539,3540],{},"t.Join();    \u002F\u002F chờ xong\n",[533,3542,3543],{"class":535,"line":560},[533,3544,564],{"emptyLinePlaceholder":563},[533,3546,3547],{"class":535,"line":567},[533,3548,3549],{},"\u002F\u002F Task — chuẩn hiện đại\n",[533,3551,3552],{"class":535,"line":573},[533,3553,3554],{},"var task = Task.Run(() => HeavyWork());\n",[533,3556,3557],{"class":535,"line":579},[533,3558,3559],{},"await task;\n",[533,3561,3562],{"class":535,"line":709},[533,3563,564],{"emptyLinePlaceholder":563},[533,3565,3566],{"class":535,"line":715},[533,3567,3568],{},"\u002F\u002F Multiple parallel\n",[533,3570,3571],{"class":535,"line":721},[533,3572,3573],{},"var tasks = users.Select(u => FetchOrdersAsync(u.Id)).ToList();\n",[533,3575,3576],{"class":535,"line":727},[533,3577,3578],{},"await Task.WhenAll(tasks);\n",[506,3580,3582,3583,2882,3585,3588],{"id":3581},"_65-bẫy-result-wait-deadlock","6.5. 🔴 Bẫy ",[476,3584,490],{},[476,3586,3587],{},".Wait()"," — deadlock",[493,3590,3591,3605,3608,3619,3626],{"color":1985,"icon":1986},[431,3592,952,3593,3596,3597,1392,3599,3601,3602,1396],{},[442,3594,3595],{},"Trong môi trường có SynchronizationContext"," (ASP.NET classic, WPF, WinForms), gọi ",[476,3598,490],{},[476,3600,3587],{}," trên Task → ",[442,3603,3604],{},"deadlock",[431,3606,3607],{},"Vì:",[587,3609,3610,3613,3616],{},[438,3611,3612],{},"Caller block UI\u002Frequest thread.",[438,3614,3615],{},"Task continuation (sau await) cần resume trên SynchronizationContext gốc.",[438,3617,3618],{},"Context gốc = thread đang bị block → continuation không chạy được → Task không complete → caller chờ vô tận.",[431,3620,3621,3622,3625],{},"ASP.NET Core ",[442,3623,3624],{},"không có SynchronizationContext"," → ít fatal hơn, nhưng vẫn lãng phí thread.",[431,3627,3628,2835,3630,3633],{},[442,3629,2972],{},[2837,3631,3632],{},"\"Async all the way\""," — đừng mix sync ↔ async.",[524,3635,3637],{"className":526,"code":3636,"language":528,"meta":529,"style":529},"\u002F\u002F ❌ Deadlock kinh điển ASP.NET classic\npublic IActionResult Index() {\n    var user = GetUserAsync(1).Result;    \u002F\u002F deadlock!\n    return View(user);\n}\n\n\u002F\u002F ✅ Async all the way\npublic async Task\u003CIActionResult> Index() {\n    var user = await GetUserAsync(1);\n    return View(user);\n}\n",[476,3638,3639,3644,3649,3654,3659,3663,3667,3672,3677,3682,3686],{"__ignoreMap":529},[533,3640,3641],{"class":535,"line":536},[533,3642,3643],{},"\u002F\u002F ❌ Deadlock kinh điển ASP.NET classic\n",[533,3645,3646],{"class":535,"line":542},[533,3647,3648],{},"public IActionResult Index() {\n",[533,3650,3651],{"class":535,"line":548},[533,3652,3653],{},"    var user = GetUserAsync(1).Result;    \u002F\u002F deadlock!\n",[533,3655,3656],{"class":535,"line":554},[533,3657,3658],{},"    return View(user);\n",[533,3660,3661],{"class":535,"line":560},[533,3662,730],{},[533,3664,3665],{"class":535,"line":567},[533,3666,564],{"emptyLinePlaceholder":563},[533,3668,3669],{"class":535,"line":573},[533,3670,3671],{},"\u002F\u002F ✅ Async all the way\n",[533,3673,3674],{"class":535,"line":579},[533,3675,3676],{},"public async Task\u003CIActionResult> Index() {\n",[533,3678,3679],{"class":535,"line":709},[533,3680,3681],{},"    var user = await GetUserAsync(1);\n",[533,3683,3684],{"class":535,"line":715},[533,3685,3658],{},[533,3687,3688],{"class":535,"line":721},[533,3689,730],{},[506,3691,3693,3694,3697],{"id":3692},"_66-async-void-chỉ-event-handler","6.6. ",[476,3695,3696],{},"async void"," — chỉ event handler",[524,3699,3701],{"className":526,"code":3700,"language":528,"meta":529,"style":529},"\u002F\u002F ❌ Thường sai\npublic async void DoStuff() {\n    await SomeAsync();\n}\n\n\u002F\u002F ✅ Đúng — không await được, exception khó catch\npublic async Task DoStuff() {\n    await SomeAsync();\n}\n\n\u002F\u002F ✅ Event handler — exception case\nbutton.Click += async (sender, e) => {\n    await SaveAsync();    \u002F\u002F OK\n};\n",[476,3702,3703,3708,3713,3718,3722,3726,3731,3736,3740,3744,3748,3753,3758,3763],{"__ignoreMap":529},[533,3704,3705],{"class":535,"line":536},[533,3706,3707],{},"\u002F\u002F ❌ Thường sai\n",[533,3709,3710],{"class":535,"line":542},[533,3711,3712],{},"public async void DoStuff() {\n",[533,3714,3715],{"class":535,"line":548},[533,3716,3717],{},"    await SomeAsync();\n",[533,3719,3720],{"class":535,"line":554},[533,3721,730],{},[533,3723,3724],{"class":535,"line":560},[533,3725,564],{"emptyLinePlaceholder":563},[533,3727,3728],{"class":535,"line":567},[533,3729,3730],{},"\u002F\u002F ✅ Đúng — không await được, exception khó catch\n",[533,3732,3733],{"class":535,"line":573},[533,3734,3735],{},"public async Task DoStuff() {\n",[533,3737,3738],{"class":535,"line":579},[533,3739,3717],{},[533,3741,3742],{"class":535,"line":709},[533,3743,730],{},[533,3745,3746],{"class":535,"line":715},[533,3747,564],{"emptyLinePlaceholder":563},[533,3749,3750],{"class":535,"line":721},[533,3751,3752],{},"\u002F\u002F ✅ Event handler — exception case\n",[533,3754,3755],{"class":535,"line":727},[533,3756,3757],{},"button.Click += async (sender, e) => {\n",[533,3759,3760],{"class":535,"line":733},[533,3761,3762],{},"    await SaveAsync();    \u002F\u002F OK\n",[533,3764,3765],{"class":535,"line":738},[533,3766,1641],{},[431,3768,3769,3771],{},[476,3770,3696],{}," có vấn đề:",[435,3773,3774,3777],{},[438,3775,3776],{},"Không await được → caller không biết khi nào xong.",[438,3778,3779],{},"Exception throw vào SynchronizationContext → có thể crash app.",[506,3781,3783,3784,3787],{"id":3782},"_67-configureawaitfalse-library-best-practice","6.7. ",[476,3785,3786],{},"ConfigureAwait(false)"," — library best practice",[524,3789,3791],{"className":526,"code":3790,"language":528,"meta":529,"style":529},"\u002F\u002F Library code — không depend SynchronizationContext của caller\npublic async Task\u003CUser> GetUserAsync(int id) {\n    var data = await _http.GetStringAsync(...).ConfigureAwait(false);\n    return Parse(data);\n}\n",[476,3792,3793,3798,3802,3807,3812],{"__ignoreMap":529},[533,3794,3795],{"class":535,"line":536},[533,3796,3797],{},"\u002F\u002F Library code — không depend SynchronizationContext của caller\n",[533,3799,3800],{"class":535,"line":542},[533,3801,3428],{},[533,3803,3804],{"class":535,"line":548},[533,3805,3806],{},"    var data = await _http.GetStringAsync(...).ConfigureAwait(false);\n",[533,3808,3809],{"class":535,"line":554},[533,3810,3811],{},"    return Parse(data);\n",[533,3813,3814],{"class":535,"line":560},[533,3815,730],{},[431,3817,3818,3820],{},[476,3819,3786],{}," báo \"không cần quay về SynchronizationContext gốc sau await\" → tránh deadlock + tăng performance.",[493,3822,1297,3823,3826,3827,3830],{"color":495,"icon":496},[442,3824,3825],{},"ASP.NET Core không cần"," ConfigureAwait(false) vì không có SyncContext. Nhưng library reusable (publish NuGet) ",[442,3828,3829],{},"vẫn nên dùng"," để an toàn cho caller dùng WPF\u002FWinForms.",[499,3832],{},[426,3834,3836],{"id":3835},"_7-câu-hỏi-tự-test-cuối-ngày","7. Câu hỏi tự test cuối ngày",[493,3838,3840,3845,3863,3881,3899],{"color":495,"icon":3839},"i-lucide-help-circle",[431,3841,3842],{},[442,3843,3844],{},"🟢 Intern:",[587,3846,3847,3850,3856],{},[438,3848,3849],{},"Vì sao có Generic? Giải quyết vấn đề gì so với ArrayList?",[438,3851,3852,3855],{},[476,3853,3854],{},"Dictionary"," lookup là O(?) — vì sao?",[438,3857,3858,959,3860,3862],{},[476,3859,2302],{},[476,3861,2305],{}," khác nhau ra sao?",[431,3864,3865,3868,3869,959,3871,3873,3874,3876,3877,3880],{},[442,3866,3867],{},"🔵 Junior:","\n4. ",[476,3870,1354],{},[476,3872,1993],{}," khác gì? Cho ví dụ EF Core.\n5. Deferred execution là gì? Cho ví dụ bug do enumerate query 2 lần.\n6. Closure trong C# bắt VALUE hay VARIABLE? Cho ví dụ.\n7. ",[476,3875,478],{}," có tạo thread mới không? Giải thích.\n8. Khi nào dùng ",[476,3878,3879],{},"Task.Run"," cho CPU bound, khi nào KHÔNG dùng cho I\u002FO?",[431,3882,3883,3886,3887,3889,3890,3892,3893,3895,3896,3898],{},[442,3884,3885],{},"🟡 Mid:","\n9. ",[476,3888,1415],{}," hoạt động ra sao? Compiler sinh code gì?\n10. Vì sao ",[476,3891,2877],{}," tốt hơn delegate public?\n11. State machine của ",[476,3894,478],{}," — mô tả?\n12. ",[476,3897,3786],{}," để làm gì? Khi nào nên dùng?",[431,3900,3901,3904,3905,3907,3908,959,3911,3914,3915],{},[442,3902,3903],{},"🔴 Senior:","\n13. Generic specialization — C# khác Java thế nào?\n14. Deadlock với ",[476,3906,490],{}," trong ASP.NET classic — giải thích cơ chế.\n15. ",[476,3909,3910],{},"Task.WhenAll",[476,3912,3913],{},"Task.WaitAll"," — khác nhau cơ bản nào?\n16. Channel",[1261,3916,3917],{}," (System.Threading.Channels) khi nào dùng?",[431,3919,3920,2835,3923,1396],{},[442,3921,3922],{},"Đáp án:",[3924,3925,3926],"a",{"href":74},"Ngân hàng câu hỏi C#",[499,3928],{},[431,3930,3931,3932],{},"➡️ Ngày mai: ",[3924,3933,3934],{"href":48},"Ngày 4 — Database & SQL",[3936,3937,3938],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":529,"searchDepth":542,"depth":542,"links":3940},[3941,3942,3950,3959,3967,3976,3981,3993],{"id":428,"depth":542,"text":429},{"id":503,"depth":542,"text":504,"children":3943},[3944,3945,3946,3947,3949],{"id":508,"depth":548,"text":509},{"id":603,"depth":548,"text":604},{"id":662,"depth":548,"text":663},{"id":784,"depth":548,"text":3948},"1.4. Constraint — where T : ...",{"id":945,"depth":548,"text":946},{"id":1018,"depth":542,"text":1019,"children":3951},[3952,3953,3954,3955,3957],{"id":1022,"depth":548,"text":1023},{"id":1258,"depth":548,"text":1259},{"id":1313,"depth":548,"text":1314},{"id":1350,"depth":548,"text":3956},"2.4. IEnumerable vs ICollection vs IList — kế thừa",{"id":1411,"depth":548,"text":3958},"2.5. yield return — iterator lazy",{"id":1530,"depth":542,"text":1531,"children":3960},[3961,3962,3963,3964,3965],{"id":1534,"depth":548,"text":1535},{"id":1610,"depth":548,"text":1611},{"id":1853,"depth":548,"text":1854},{"id":2009,"depth":548,"text":2010},{"id":2122,"depth":548,"text":3966},"3.5. Cơ chế bên trong — Where thực sự làm gì?",{"id":2209,"depth":542,"text":2210,"children":3968},[3969,3970,3972,3973,3974,3975],{"id":2213,"depth":548,"text":2214},{"id":2298,"depth":548,"text":3971},"4.2. Action, Func, Predicate — built-in delegate",{"id":2473,"depth":548,"text":2474},{"id":2562,"depth":548,"text":2563},{"id":2708,"depth":548,"text":2709},{"id":2826,"depth":548,"text":2827},{"id":2891,"depth":542,"text":2892,"children":3977},[3978,3979,3980],{"id":2895,"depth":548,"text":2896},{"id":2989,"depth":548,"text":2990},{"id":3019,"depth":548,"text":3020},{"id":3076,"depth":542,"text":3077,"children":3982},[3983,3984,3985,3986,3987,3989,3991],{"id":3080,"depth":548,"text":3081},{"id":3097,"depth":548,"text":3098},{"id":3355,"depth":548,"text":3356},{"id":3486,"depth":548,"text":3487},{"id":3581,"depth":548,"text":3988},"6.5. 🔴 Bẫy .Result \u002F .Wait() — deadlock",{"id":3692,"depth":548,"text":3990},"6.6. async void — chỉ event handler",{"id":3782,"depth":548,"text":3992},"6.7. ConfigureAwait(false) — library best practice",{"id":3835,"depth":542,"text":3836},"Generic internals, LINQ deferred execution, async\u002Fawait state machine, delegate vs event, extension method. Giải thích sâu cho mọi level.","md",null,{},{"title":42,"icon":45},{"title":42,"description":3994},"epB7o9t1FYWoK0Er5bc3NPlHE5Ler00Uf_VWImQKzuQ",[4002,4004],{"title":37,"path":38,"stem":39,"description":4003,"icon":40,"children":-1},"4 tính chất OOP, Interface vs Abstract class, 5 nguyên lý SOLID kèm ví dụ C Sharp.",{"title":47,"path":48,"stem":49,"description":4005,"icon":50,"children":-1},"B-tree INDEX internals, JOIN sâu, MVCC, ACID, isolation level mechanism, query plan. Mock data thật để test query.",1783490353308]