├── 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 |
--------------------------------------------------------------------------------