├── Demo_ExtensionMethods ├── Demo_ExtensionMethods.csproj ├── .claude │ └── settings.local.json ├── DateTimeExtensionMembers.cs ├── .gitignore ├── DateTimeExtensions.cs ├── Program.cs └── README.md ├── Griffin.CSharp14Demos.sln ├── CLAUDE.md └── README.md /Demo_ExtensionMethods/Demo_ExtensionMethods.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net10.0 6 | 14.0 7 | enable 8 | enable 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/.claude/settings.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "allow": [ 4 | "mcp__MCP_DOCKER__get-library-docs", 5 | "Bash(dotnet build:*)", 6 | "Bash(Select-String -Pattern \"DateTimeExtensionMembers\")", 7 | "Bash(Select-Object -First 5)", 8 | "Bash(dotnet run:*)", 9 | "WebSearch", 10 | "WebFetch(domain:andrewlock.net)" 11 | ], 12 | "deny": [], 13 | "ask": [] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Griffin.CSharp14Demos.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.5.2.0 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo_ExtensionMethods", "Demo_ExtensionMethods\Demo_ExtensionMethods.csproj", "{AF471F05-5600-9B9E-DDC3-4626F28BC5D4}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {AF471F05-5600-9B9E-DDC3-4626F28BC5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {AF471F05-5600-9B9E-DDC3-4626F28BC5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {AF471F05-5600-9B9E-DDC3-4626F28BC5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {AF471F05-5600-9B9E-DDC3-4626F28BC5D4}.Release|Any CPU.Build.0 = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(SolutionProperties) = preSolution 19 | HideSolutionNode = FALSE 20 | EndGlobalSection 21 | GlobalSection(ExtensibilityGlobals) = postSolution 22 | SolutionGuid = {CB97169D-459A-479E-97EF-EC13D43CCAA4} 23 | EndGlobalSection 24 | EndGlobal 25 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/DateTimeExtensionMembers.cs: -------------------------------------------------------------------------------- 1 | namespace Demo_ExtensionMethods; 2 | 3 | /// 4 | /// Modern C# 14 extension members approach 5 | /// These read like native properties - no method call syntax needed! 6 | /// This is the semantic evolution: "properties" not "methods" 7 | /// 8 | public static class DateTimeExtensionMembers 9 | { 10 | extension(DateTime date) 11 | { 12 | /// 13 | /// Gets the Monday of the current week for the given date 14 | /// 15 | public DateTime MondayOfCurrentWeek 16 | { 17 | get 18 | { 19 | int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7; 20 | return date.Date.AddDays(-diff); 21 | } 22 | } 23 | 24 | /// 25 | /// Gets the first day of the month 26 | /// 27 | public DateTime StartOfMonth => new DateTime(date.Year, date.Month, 1); 28 | 29 | /// 30 | /// Gets the last day of the month 31 | /// 32 | public DateTime EndOfMonth => new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1); 33 | 34 | /// 35 | /// Gets the first day of the year 36 | /// 37 | public DateTime StartOfYear => new DateTime(date.Year, 1, 1); 38 | 39 | /// 40 | /// Determines if the date falls on a weekend 41 | /// 42 | public bool IsWeekend => date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/.gitignore: -------------------------------------------------------------------------------- 1 | # Build results 2 | [Dd]ebug/ 3 | [Dd]ebugPublic/ 4 | [Rr]elease/ 5 | [Rr]eleases/ 6 | x64/ 7 | x86/ 8 | [Ww][Ii][Nn]32/ 9 | [Aa][Rr][Mm]/ 10 | [Aa][Rr][Mm]64/ 11 | bld/ 12 | [Bb]in/ 13 | [Oo]bj/ 14 | [Ll]og/ 15 | [Ll]ogs/ 16 | 17 | # Visual Studio cache/options 18 | .vs/ 19 | .vscode/ 20 | *.suo 21 | *.user 22 | *.userosscache 23 | *.sln.docstates 24 | 25 | # Build Results of an ATL Project 26 | [Dd]ebugPS/ 27 | [Rr]eleasePS/ 28 | dlldata.c 29 | 30 | # .NET Core 31 | project.lock.json 32 | project.fragment.lock.json 33 | artifacts/ 34 | 35 | # Files built by Visual Studio 36 | *_i.c 37 | *_p.c 38 | *_h.h 39 | *.ilk 40 | *.meta 41 | *.obj 42 | *.iobj 43 | *.pch 44 | *.pdb 45 | *.ipdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *_wpftmp.csproj 56 | *.log 57 | *.tlog 58 | *.vspscc 59 | *.vssscc 60 | .builds 61 | *.pidb 62 | *.svclog 63 | *.scc 64 | 65 | # NuGet Packages 66 | *.nupkg 67 | *.snupkg 68 | **/packages/* 69 | !**/packages/build/ 70 | *.nuget.props 71 | *.nuget.targets 72 | 73 | # Visual Studio profiler 74 | *.psess 75 | *.vsp 76 | *.vspx 77 | *.sap 78 | 79 | # ReSharper 80 | _ReSharper*/ 81 | *.[Rr]e[Ss]harper 82 | *.DotSettings.user 83 | 84 | # Rider 85 | .idea/ 86 | *.sln.iml 87 | 88 | # User-specific files 89 | *.rsuser 90 | *.userprefs 91 | 92 | # Mono auto generated files 93 | mono_crash.* 94 | 95 | # Windows image file caches 96 | Thumbs.db 97 | ehthumbs.db 98 | 99 | # Folder config file 100 | Desktop.ini 101 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Demo_ExtensionMethods; 2 | 3 | /// 4 | /// Traditional C# extension methods approach (pre-C# 14) 5 | /// These work, but require method call syntax even for conceptual properties 6 | /// 7 | public static class DateTimeExtensions 8 | { 9 | /// 10 | /// Gets the Monday of the current week for the given date 11 | /// 12 | public static DateTime MondayOfCurrentWeek_EM(this DateTime date) 13 | { 14 | int diff = (7 + (date.DayOfWeek - DayOfWeek.Monday)) % 7; 15 | return date.Date.AddDays(-diff); 16 | } 17 | 18 | /// 19 | /// Gets the first day of the month 20 | /// 21 | public static DateTime StartOfMonth_EM(this DateTime date) 22 | { 23 | return new DateTime(date.Year, date.Month, 1); 24 | } 25 | 26 | /// 27 | /// Gets the last day of the month 28 | /// 29 | public static DateTime EndOfMonth_EM(this DateTime date) 30 | { 31 | return date.StartOfMonth_EM().AddMonths(1).AddDays(-1); 32 | } 33 | 34 | /// 35 | /// Gets the first day of the year 36 | /// 37 | public static DateTime StartOfYear_EM(this DateTime date) 38 | { 39 | return new DateTime(date.Year, 1, 1); 40 | } 41 | 42 | /// 43 | /// Determines if the date falls on a weekend 44 | /// 45 | public static bool IsWeekend_EM(this DateTime date) 46 | { 47 | return date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | # CLAUDE.md 2 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 | 5 | ## Project Overview 6 | 7 | This is a C# 14 demonstration repository showcasing modern language features, specifically focusing on **extension members** - a new C# 14 feature that allows adding property-like syntax to existing types (as opposed to traditional extension methods that require method call syntax). 8 | 9 | ## Build and Run Commands 10 | 11 | ### Build the Solution 12 | ```bash 13 | dotnet build Griffin.CSharp14Demos.sln 14 | ``` 15 | 16 | ### Run a Specific Demo 17 | ```bash 18 | cd Demo_ExtensionMethods 19 | dotnet run 20 | ``` 21 | 22 | ### Build Individual Project 23 | ```bash 24 | dotnet build Demo_ExtensionMethods/Demo_ExtensionMethods.csproj 25 | ``` 26 | 27 | ## Critical Configuration Requirements 28 | 29 | - **Target Framework**: .NET 10.0 (`net10.0`) 30 | - **C# Language Version**: 14.0 (`14.0`) 31 | - **Nullable Reference Types**: Enabled 32 | - **Implicit Usings**: Enabled 33 | 34 | When creating new demo projects in this repository, ensure the .csproj file includes: 35 | ```xml 36 | net10.0 37 | 14.0 38 | ``` 39 | 40 | ## Architecture: Extension Members Pattern 41 | 42 | ### Core Concept 43 | This repository demonstrates the semantic evolution from extension methods to extension members: 44 | 45 | **Extension Methods (Pre-C# 14)**: 46 | ```csharp 47 | public static class DateTimeExtensions 48 | { 49 | public static DateTime StartOfMonth(this DateTime date) => ...; 50 | } 51 | // Usage: date.StartOfMonth() ← requires parentheses 52 | ``` 53 | 54 | **Extension Members (C# 14)**: 55 | ```csharp 56 | public static class DateTimeExtensionMembers 57 | { 58 | extension(DateTime date) 59 | { 60 | public DateTime StartOfMonth => new DateTime(date.Year, date.Month, 1); 61 | } 62 | } 63 | // Usage: date.StartOfMonth ← clean property syntax 64 | ``` 65 | 66 | ### When to Use Extension Members vs Extension Methods 67 | 68 | - **Use extension members** when adding characteristics/properties (e.g., `IsWeekend`, `StartOfMonth`) 69 | - **Use extension methods** when adding actions/operations (e.g., `AddBusinessDays()`, `Format()`) 70 | 71 | ## Demo Project Structure 72 | 73 | Each demo project follows this pattern: 74 | - `Program.cs` - Interactive demonstration with console output 75 | - Feature-specific files demonstrating old vs. new approaches 76 | - `README.md` - Detailed explanation with examples and sample output 77 | 78 | ## Naming Conventions 79 | 80 | In demo code, suffixes are used to distinguish between old and new approaches: 81 | - `_EM` suffix on extension methods indicates "Extension Method" (old approach) 82 | - No suffix on extension members (new approach, preferred) 83 | 84 | Example: 85 | - `MondayOfCurrentWeek_EM()` - old extension method 86 | - `MondayOfCurrentWeek` - new extension member 87 | 88 | ## Adding New Demos 89 | 90 | When adding new C# 14 feature demonstrations: 91 | 92 | 1. Create a new project folder: `Demo_{FeatureName}/` 93 | 2. Add the project to `Griffin.CSharp14Demos.sln` 94 | 3. Include both traditional and C# 14 approaches for comparison 95 | 4. Create a comprehensive README.md with: 96 | - Problem statement (why the old way is problematic) 97 | - Solution explanation (how C# 14 improves it) 98 | - Side-by-side code examples 99 | - Sample output 100 | 5. Implement a `Program.cs` that clearly demonstrates the difference 101 | 102 | ## Code Style 103 | 104 | - Use expression-bodied members for simple properties (`=>` syntax) 105 | - Include XML documentation comments on all public members 106 | - Use pattern matching where appropriate (e.g., `is DayOfWeek.Saturday or DayOfWeek.Sunday`) 107 | - Console output should use box-drawing characters for visual separation 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C# 14 Feature Demonstrations 2 | 3 | A collection of hands-on demonstrations showcasing the latest features in C# 14, with side-by-side comparisons to traditional approaches. 4 | 5 | ## Overview 6 | 7 | C# 14 introduces powerful new language features that improve code expressiveness, reduce boilerplate, and better align syntax with semantic intent. This repository provides practical, real-world examples of these features to help developers understand not just *what* changed, but *why* it matters. 8 | 9 | Each demo includes: 10 | - **Problem Statement** - What limitation existed in previous C# versions 11 | - **Solution** - How C# 14 addresses it 12 | - **Side-by-Side Comparison** - Traditional vs. modern approach 13 | - **Real-World Examples** - Practical usage scenarios 14 | - **Detailed Explanations** - Why the new way is better 15 | 16 | ## Requirements 17 | 18 | - **.NET 10 SDK** (or later) 19 | - **C# 14** language support 20 | - Any IDE with C# support (Visual Studio 2025+, JetBrains Rider, VS Code) 21 | 22 | ### Verify Your Setup 23 | 24 | ```bash 25 | dotnet --version # Should show 10.x or higher 26 | ``` 27 | 28 | ## Getting Started 29 | 30 | ### Clone the Repository 31 | ```bash 32 | git clone 33 | cd Griffin.CSharp14Demos 34 | ``` 35 | 36 | ### Build All Demos 37 | ```bash 38 | dotnet build Griffin.CSharp14Demos.sln 39 | ``` 40 | 41 | ### Run a Specific Demo 42 | ```bash 43 | cd Demo_ExtensionMethods 44 | dotnet run 45 | ``` 46 | 47 | ## Demos 48 | 49 | ### 1. Extension Members 50 | 51 | **Location**: `Demo_ExtensionMethods/` 52 | 53 | **What it demonstrates**: The evolution from extension methods to extension members, allowing property-like syntax for characteristics instead of forcing method call syntax. 54 | 55 | **Key Concept**: 56 | ```csharp 57 | // Old Way: Extension Method (requires parentheses) 58 | var monday = date.MondayOfCurrentWeek(); 59 | 60 | // New Way: Extension Member (property syntax) 61 | var monday = date.MondayOfCurrentWeek; 62 | ``` 63 | 64 | **Run it**: 65 | ```bash 66 | cd Demo_ExtensionMethods 67 | dotnet run 68 | ``` 69 | 70 | [📖 Read the full demo documentation](Demo_ExtensionMethods/README.md) 71 | 72 | --- 73 | 74 | ### More Demos Coming Soon! 75 | 76 | This repository will be expanded with additional C# 14 feature demonstrations including: 77 | - Params collections 78 | - Field keyword in properties 79 | - Lock object improvements 80 | - And more... 81 | 82 | ## Repository Structure 83 | 84 | ``` 85 | Griffin.CSharp14Demos/ 86 | ├── Griffin.CSharp14Demos.sln # Solution file 87 | ├── README.md # This file 88 | ├── CLAUDE.md # AI assistant guidance 89 | │ 90 | ├── Demo_ExtensionMethods/ # Extension Members demo 91 | │ ├── Demo_ExtensionMethods.csproj 92 | │ ├── Program.cs 93 | │ ├── DateTimeExtensions.cs # Traditional approach 94 | │ ├── DateTimeExtensionMembers.cs # C# 14 approach 95 | │ └── README.md 96 | │ 97 | └── [Future Demos]/ 98 | ``` 99 | 100 | ## Contributing New Demos 101 | 102 | Want to add a new C# 14 feature demonstration? Follow this pattern: 103 | 104 | 1. **Create a new project folder**: `Demo_{FeatureName}/` 105 | 2. **Configure for C# 14**: 106 | ```xml 107 | net10.0 108 | 14.0 109 | ``` 110 | 3. **Include both approaches**: Show the old way vs. the new C# 14 way 111 | 4. **Add comprehensive README**: Explain the problem, solution, and real-world usage 112 | 5. **Create runnable demo**: `Program.cs` with clear console output 113 | 6. **Update this README**: Add your demo to the demos list 114 | 115 | ## Why This Repository? 116 | 117 | C# 14 isn't just about new syntax - it's about writing code that **says what it means**. These demos focus on: 118 | 119 | - **Semantic Clarity** - Code that reads like natural language 120 | - **Practical Application** - Real-world scenarios, not just toy examples 121 | - **Comparative Learning** - Understanding *why* the new way is better 122 | - **Educational Value** - Teaching through clear, documented examples 123 | 124 | ## Learn More 125 | 126 | - [C# Language Design Repository](https://github.com/dotnet/csharplang) 127 | - [What's New in C# 14](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14) 128 | - [.NET Blog](https://devblogs.microsoft.com/dotnet/) 129 | 130 | ## License 131 | 132 | This repository is for educational purposes. 133 | 134 | --- 135 | 136 | **Each feature demonstration is designed to be self-contained and runnable.** Explore each demo's README for detailed explanations and sample output. 137 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/Program.cs: -------------------------------------------------------------------------------- 1 | using Demo_ExtensionMethods; 2 | 3 | Console.WriteLine("═══════════════════════════════════════════════════════════════"); 4 | Console.WriteLine(" C# 14 Extension Members Demo: DateTime Extensions"); 5 | Console.WriteLine("═══════════════════════════════════════════════════════════════\n"); 6 | 7 | var today = DateTime.Now; 8 | 9 | Console.WriteLine($"Today's Date: {today:dddd, MMMM d, yyyy}\n"); 10 | 11 | // ═══════════════════════════════════════════════════════════════ 12 | // Part 1: OLD WAY - Extension Methods (Pre-C# 14) 13 | // ═══════════════════════════════════════════════════════════════ 14 | Console.WriteLine("───────────────────────────────────────────────────────────────"); 15 | Console.WriteLine(" OLD WAY: Extension Methods (requires parentheses)"); 16 | Console.WriteLine("───────────────────────────────────────────────────────────────\n"); 17 | 18 | // Notice: We HAVE to call these as methods with () 19 | // Even though conceptually they're properties/characteristics of the date 20 | var mondayOld = today.MondayOfCurrentWeek_EM(); 21 | var startOfMonthOld = today.StartOfMonth_EM(); 22 | var endOfMonthOld = today.EndOfMonth_EM(); 23 | var startOfYearOld = today.StartOfYear_EM(); 24 | var isWeekendOld = today.IsWeekend_EM(); 25 | 26 | Console.WriteLine($" today.MondayOfCurrentWeek_EM() = {mondayOld:dddd, MMMM d, yyyy}"); 27 | Console.WriteLine($" today.StartOfMonth_EM() = {startOfMonthOld:dddd, MMMM d, yyyy}"); 28 | Console.WriteLine($" today.EndOfMonth_EM() = {endOfMonthOld:dddd, MMMM d, yyyy}"); 29 | Console.WriteLine($" today.StartOfYear_EM() = {startOfYearOld:dddd, MMMM d, yyyy}"); 30 | Console.WriteLine($" today.IsWeekend_EM() = {isWeekendOld}"); 31 | 32 | Console.WriteLine("\n 💭 Problem: These LOOK like actions/verbs, but they're really"); 33 | Console.WriteLine(" just asking for a property/characteristic of the date.\n"); 34 | 35 | // ═══════════════════════════════════════════════════════════════ 36 | // Part 2: NEW WAY - Extension Members (C# 14) 37 | // ═══════════════════════════════════════════════════════════════ 38 | Console.WriteLine("───────────────────────────────────────────────────────────────"); 39 | Console.WriteLine(" NEW WAY: Extension Members (property syntax!)"); 40 | Console.WriteLine("───────────────────────────────────────────────────────────────\n"); 41 | 42 | // Notice: No parentheses! These read like natural properties 43 | // This is the semantic clarity we've been wanting 44 | var mondayNew = today.MondayOfCurrentWeek; 45 | var startOfMonthNew = today.StartOfMonth; 46 | var endOfMonthNew = today.EndOfMonth; 47 | var startOfYearNew = today.StartOfYear; 48 | var isWeekendNew = today.IsWeekend; 49 | 50 | Console.WriteLine($" today.MondayOfCurrentWeek = {mondayNew:dddd, MMMM d, yyyy}"); 51 | Console.WriteLine($" today.StartOfMonth = {startOfMonthNew:dddd, MMMM d, yyyy}"); 52 | Console.WriteLine($" today.EndOfMonth = {endOfMonthNew:dddd, MMMM d, yyyy}"); 53 | Console.WriteLine($" today.StartOfYear = {startOfYearNew:dddd, MMMM d, yyyy}"); 54 | Console.WriteLine($" today.IsWeekend = {isWeekendNew}"); 55 | 56 | Console.WriteLine("\n ✨ Solution: These read like native properties of DateTime!"); 57 | Console.WriteLine(" No mental overhead. Just natural, expressive code.\n"); 58 | 59 | // ═══════════════════════════════════════════════════════════════ 60 | // Part 3: Real-World Usage Examples 61 | // ═══════════════════════════════════════════════════════════════ 62 | Console.WriteLine("───────────────────────────────────────────────────────────────"); 63 | Console.WriteLine(" REAL-WORLD EXAMPLES"); 64 | Console.WriteLine("───────────────────────────────────────────────────────────────\n"); 65 | 66 | // Example 1: Week-based reporting 67 | Console.WriteLine(" Example 1: Weekly Report Range"); 68 | Console.WriteLine(" ──────────────────────────────"); 69 | var reportStart = today.MondayOfCurrentWeek; 70 | var reportEnd = reportStart.AddDays(6); 71 | Console.WriteLine($" Week of {reportStart:MM/dd} - {reportEnd:MM/dd}"); 72 | Console.WriteLine($" Report covers: {reportStart:dddd, MMMM d} through {reportEnd:dddd, MMMM d}\n"); 73 | 74 | // Example 2: Month boundaries for data queries 75 | Console.WriteLine(" Example 2: Monthly Data Range"); 76 | Console.WriteLine(" ─────────────────────────────"); 77 | Console.WriteLine($" Query from: {today.StartOfMonth:yyyy-MM-dd}"); 78 | Console.WriteLine($" Query to: {today.EndOfMonth:yyyy-MM-dd}\n"); 79 | 80 | // Example 3: Year-to-date calculations 81 | Console.WriteLine(" Example 3: Year-to-Date Metrics"); 82 | Console.WriteLine(" ───────────────────────────────"); 83 | var yearStart = today.StartOfYear; 84 | var daysSinceYearStart = (today - yearStart).Days; 85 | Console.WriteLine($" Year started: {yearStart:MMMM d, yyyy}"); 86 | Console.WriteLine($" Days elapsed: {daysSinceYearStart} days\n"); 87 | 88 | // Example 4: Conditional logic with weekend check 89 | Console.WriteLine(" Example 4: Weekend-Aware Scheduling"); 90 | Console.WriteLine(" ───────────────────────────────────"); 91 | if (today.IsWeekend) 92 | { 93 | Console.WriteLine($" Today ({today:dddd}) is a weekend - no scheduled tasks."); 94 | } 95 | else 96 | { 97 | var nextMonday = today.MondayOfCurrentWeek.AddDays(7); 98 | Console.WriteLine($" Today ({today:dddd}) is a weekday - tasks active."); 99 | Console.WriteLine($" Next planning session: {nextMonday:dddd, MMMM d}"); 100 | } 101 | 102 | Console.WriteLine("\n═══════════════════════════════════════════════════════════════"); 103 | Console.WriteLine(" KEY TAKEAWAY"); 104 | Console.WriteLine("═══════════════════════════════════════════════════════════════"); 105 | Console.WriteLine(" Extension members let your code SAY WHAT IT MEANS."); 106 | Console.WriteLine(" No more faking properties with methods. Just clean semantics."); 107 | Console.WriteLine("═══════════════════════════════════════════════════════════════\n"); 108 | -------------------------------------------------------------------------------- /Demo_ExtensionMethods/README.md: -------------------------------------------------------------------------------- 1 | # C# 14 Extension Members Demo 2 | 3 | ## Overview 4 | 5 | This project demonstrates the evolution from **extension methods** (traditional C#) to **extension members** (C# 14), using `DateTime` as a real-world example. 6 | 7 | ## The Problem 8 | 9 | Have you ever written code like this? 10 | 11 | ```csharp 12 | var monday = DateTime.Now.MondayOfCurrentWeek(); 13 | ``` 14 | 15 | It *works*, but there's a semantic mismatch: 16 | - **"Monday of the current week"** isn't an *action* you perform on a date 17 | - It's a *characteristic* or *property* of that date 18 | 19 | Yet traditional C# forced us to use method syntax `()` even when we conceptually wanted a property. 20 | 21 | ## The Solution: Extension Members (C# 14) 22 | 23 | With C# 14's extension members, you can now write: 24 | 25 | ```csharp 26 | var monday = DateTime.Now.MondayOfCurrentWeek; // No parentheses! 27 | ``` 28 | 29 | This reads like natural language — like a native property of `DateTime`. 30 | 31 | ## What This Demo Shows 32 | 33 | ### 1. **DateTimeExtensions.cs** — The Old Way 34 | Traditional extension methods that require method call syntax: 35 | 36 | ```csharp 37 | public static class DateTimeExtensions 38 | { 39 | public static DateTime MondayOfCurrentWeek(this DateTime date) { ... } 40 | public static DateTime StartOfMonth(this DateTime date) { ... } 41 | public static DateTime EndOfMonth(this DateTime date) { ... } 42 | public static DateTime StartOfYear(this DateTime date) { ... } 43 | public static bool IsWeekend(this DateTime date) { ... } 44 | } 45 | ``` 46 | 47 | **Usage:** `date.MondayOfCurrentWeek()` ← requires parentheses 48 | 49 | ### 2. **DateTimeExtensionMembers.cs** — The New Way 50 | Modern C# 14 extension members using property syntax: 51 | 52 | ```csharp 53 | public extension DateTimeExtensionMembers for DateTime 54 | { 55 | public DateTime MondayOfCurrentWeek { get { ... } } 56 | public DateTime StartOfMonth => ...; 57 | public DateTime EndOfMonth => ...; 58 | public DateTime StartOfYear => ...; 59 | public bool IsWeekend => ...; 60 | } 61 | ``` 62 | 63 | **Usage:** `date.MondayOfCurrentWeek` ← clean property syntax! 64 | 65 | ### 3. **Program.cs** — Side-by-Side Comparison 66 | A comprehensive demo that shows: 67 | - The difference in syntax between old and new approaches 68 | - Real-world usage examples (reports, queries, calculations) 69 | - Why extension members provide better semantic clarity 70 | 71 | ## Running the Demo 72 | 73 | ```bash 74 | dotnet run 75 | ``` 76 | 77 | ## Sample Output 78 | 79 | ``` 80 | ═══════════════════════════════════════════════════════════════ 81 | C# 14 Extension Members Demo: DateTime Extensions 82 | ═══════════════════════════════════════════════════════════════ 83 | 84 | Today's Date: Monday, December 8, 2025 85 | 86 | ─────────────────────────────────────────────────────────────── 87 | OLD WAY: Extension Methods (requires parentheses) 88 | ─────────────────────────────────────────────────────────────── 89 | 90 | today.MondayOfCurrentWeek_EM() = Monday, December 8, 2025 91 | today.StartOfMonth_EM() = Monday, December 1, 2025 92 | today.EndOfMonth_EM() = Wednesday, December 31, 2025 93 | today.StartOfYear_EM() = Wednesday, January 1, 2025 94 | today.IsWeekend_EM() = False 95 | 96 | 💭 Problem: These LOOK like actions/verbs, but they're really 97 | just asking for a property/characteristic of the date. 98 | 99 | ─────────────────────────────────────────────────────────────── 100 | NEW WAY: Extension Members (property syntax!) 101 | ─────────────────────────────────────────────────────────────── 102 | 103 | today.MondayOfCurrentWeek = Monday, December 8, 2025 104 | today.StartOfMonth = Monday, December 1, 2025 105 | today.EndOfMonth = Wednesday, December 31, 2025 106 | today.StartOfYear = Wednesday, January 1, 2025 107 | today.IsWeekend = False 108 | 109 | ✨ Solution: These read like native properties of DateTime! 110 | No mental overhead. Just natural, expressive code. 111 | 112 | ─────────────────────────────────────────────────────────────── 113 | REAL-WORLD EXAMPLES 114 | ─────────────────────────────────────────────────────────────── 115 | 116 | Example 1: Weekly Report Range 117 | ────────────────────────────── 118 | Week of 12/08 - 12/14 119 | Report covers: Monday, December 8 through Sunday, December 14 120 | 121 | Example 2: Monthly Data Range 122 | ───────────────────────────── 123 | Query from: 2025-12-01 124 | Query to: 2025-12-31 125 | 126 | Example 3: Year-to-Date Metrics 127 | ─────────────────────────────── 128 | Year started: January 1, 2025 129 | Days elapsed: 341 days 130 | 131 | Example 4: Weekend-Aware Scheduling 132 | ─────────────────────────────────── 133 | Today (Monday) is a weekday - tasks active. 134 | Next planning session: Monday, December 15 135 | 136 | ═══════════════════════════════════════════════════════════════ 137 | KEY TAKEAWAY 138 | ═══════════════════════════════════════════════════════════════ 139 | Extension members let your code SAY WHAT IT MEANS. 140 | No more faking properties with methods. Just clean semantics. 141 | ═══════════════════════════════════════════════════════════════ 142 | ``` 143 | 144 | ## Key Takeaways 145 | 146 | ### ✨ **Extension members let your code SAY WHAT IT MEANS** 147 | 148 | - **Before:** `date.MondayOfCurrentWeek()` — looks like an action 149 | - **After:** `date.MondayOfCurrentWeek` — reads like a property 150 | 151 | ### 🎯 **When to Use Extension Members** 152 | 153 | Use extension members when you want to add: 154 | - **Properties** (not methods) to existing types 155 | - **Semantic clarity** — when the concept is a characteristic, not an action 156 | - **Natural language** — code that reads like plain English 157 | 158 | ### ⚙️ **Technical Benefits** 159 | 160 | 1. **Cleaner syntax** — no unnecessary parentheses 161 | 2. **Better semantics** — properties for characteristics, methods for actions 162 | 3. **Improved readability** — code that expresses intent clearly 163 | 4. **Consistent patterns** — aligns with how native properties work 164 | 165 | ## Requirements 166 | 167 | - **.NET 10** (or .NET 9 with preview features) 168 | - **C# 14 preview features** enabled (`preview`) 169 | 170 | ## Project Structure 171 | 172 | ``` 173 | Demo_ExtensionMethods/ 174 | ├── Demo_ExtensionMethods.csproj # Project file with C# 14 support 175 | ├── DateTimeExtensions.cs # Old approach (extension methods) 176 | ├── DateTimeExtensionMembers.cs # New approach (extension members) 177 | ├── Program.cs # Demonstration code 178 | └── README.md # This file 179 | ``` 180 | 181 | ## Further Reading 182 | 183 | - [C# 14 Extension Members Proposal](https://github.com/dotnet/csharplang/issues/5497) 184 | - [Extension Methods vs Extension Members](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14) 185 | 186 | ## License 187 | 188 | This is a demonstration project for educational purposes. 189 | 190 | --- 191 | 192 | **Bottom line:** Extension members close the semantic gap between "what you mean" and "what you write." 193 | 194 | No more faking properties with methods. Just clean, expressive code. 195 | --------------------------------------------------------------------------------