{"id":679230,"date":"2026-02-23T15:44:31","date_gmt":"2026-02-23T14:44:31","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=dotnet&#038;p=679230"},"modified":"2026-02-27T14:34:41","modified_gmt":"2026-02-27T13:34:41","slug":"csharp-extension-members","status":"publish","type":"dotnet","link":"https:\/\/blog.jetbrains.com\/zh-hans\/dotnet\/2026\/02\/23\/csharp-extension-members","title":{"rendered":"C# Extension Members"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Overview: What are extension members?<\/h2>\n\n\n\n<p>Extension members allow you to define additional members for existing types without modifying their definitions. With them, you can add functionality to existing types you don\u2019t have access to or don\u2019t control, for example, built-in types or types from an API or commercial library.&nbsp;<\/p>\n\n\n\n<p>Extension methods have been a feature of C# since version 3.0 in 2007, so the concept has been around for some time in .NET. However, traditional extension methods were just that &#8211; methods only. Extensions could not be created for properties, fields, or operators. You couldn\u2019t create static extensions and they couldn\u2019t easily participate in interfaces. However, new syntax in C# 14 allows both instance and static properties and methods, as well as operators.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Classic extension methods<\/h2>\n\n\n\n<p>Let\u2019s quickly review what a classic extension method looks like. We\u2019ll extend the <code>DateTime<\/code> structure to check the first Monday of any quarter. You might see code like this in manufacturing scenarios where production runs need to start on a specific day, such as the first Monday of a quarter. The code looks something like this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">    public static DateTime FirstMondayOfQuarter(this DateTime dateTime, int quarter)\n    {\n        if (quarter is &lt; 1 or > 4)\n            throw new ArgumentOutOfRangeException(nameof(quarter), \n                \"Quarter must be between 1 and 4.\");\n\n        var year = dateTime.Year;\n        var firstMonth = (quarter - 1) * 3 + 1;\n\n        var date = new DateTime(year, firstMonth, 1);\n\n        var offset = ((int)DayOfWeek.Monday - (int)date.DayOfWeek + 7) % 7;\n        return date.AddDays(offset);\n    }<\/pre>\n\n\n\n<p>Notice that to make the extension method you must make the class and method <code>static<\/code>, and use the <code>this<\/code> keyword to indicate which type to extend. While the definition uses the <code>static<\/code> keyword, it\u2019s not a static member. <\/p>\n\n\n\n<p>Code to use this extension method looks like the following:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">DateTime myDate = DateTime.Now;\n\nfor (var i = 1; i &lt;= 4; i++)\n{\n\u00a0\u00a0\u00a0\u00a0Console.WriteLine(myDate.FirstMondayOfQuarter(i).ToShortDateString());\n}<\/pre>\n\n\n\n<p>Because it\u2019s not a static method, you can\u2019t just call <code>DateTime.FirstMondayOfQuarter(2)<\/code>. Calling <code>DateTime.Now<\/code> (or any <code>DateTime<\/code> member) creates a new instance of a <code>DateTime<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Extension members in C# 14<\/h2>\n\n\n\n<p>Use the new <code>extension<\/code> block inside a static class to define extensions. The extension block accepts the receiver type (the type you want to make an extension for), and optionally, a receiver parameter name for instance members. Adding the parameter name is recommended for clarity. Here\u2019s the syntax:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">extension(Type) { \u2026 }\u00a0 \u00a0 \/\/ plain extension block\n\nextension(Type parameterName) { \u2026 } \u00a0 \/\/ extension block with a parameter name<\/pre>\n\n\n\n<p>If we want to convert a classic extension method to a new extension member, we can use Rider. Rider has a handy intention action for this, just press <kbd>Alt + Enter<\/kbd> and choose <em>Move to extension block:<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/02\/extension-member-migrate.png\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2026\/02\/extension-member-migrate.gif\" width=\"800\" alt=\"Animated gif showing how to use Rider to upgrade a classic method that extends the DateTime struct to calculate the first Monday of a quarter to an extension member\" class=\"wp-image-679274\"\/><\/figure>\n\n\n\n<p>The code to use it doesn&#8217;t change. However, you can now call the code without having to create an instance first, like this:<\/p>\n\n\n\n<p><code>Console.<em>WriteLine<\/em>(DateTime.Now.FirstMondayOfQuarter(i).ToShortDateString());<\/code><\/p>\n\n\n\n<p>So you won&#8217;t need to change any calling code unless you want to. <\/p>\n\n\n\n<p>To create an extension property, use an <code>extension<\/code> block like you would for any extension member. The rest of the code looks very natural like regular C# code.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public static class DateTimeExtensions\n{\n\u00a0\u00a0\u00a0\u00a0extension(DateTime date)\n\u00a0\u00a0\u00a0\u00a0{\n        public bool IsWeekend => date.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday;\n\u00a0\u00a0\u00a0\u00a0}\n}\n\n\/\/ To use it:\n\nif (DateTime.Today.IsWeekend)\n{\n\u00a0\u00a0\u00a0\u00a0\/\/ No work today, yay!\n}<\/pre>\n\n\n\n<p>Notice that in the extension block you define methods, properties, and other members without using the <code>this<\/code> parameter syntax for each member.<\/p>\n\n\n\n<p>A goal of the C# team was to ensure that existing code doesn\u2019t break, so then the syntax you use becomes a matter of style. There\u2019s no need to change any of your existing extension methods, but Rider&#8217;s handy intention action makes it fast and easy to do so. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">In Summary<\/h2>\n\n\n\n<p>Extension members are beneficial for several scenarios, including transforming helper methods into properties, organizing related extensions, incorporating static constants or factories into existing types, defining operators on external types, and making third-party APIs feel more integrated or native.<\/p>\n","protected":false},"author":901,"featured_media":683640,"comment_status":"closed","ping_status":"closed","template":"","categories":[4992],"tags":[211,8760],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/679230"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/dotnet"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/901"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=679230"}],"version-history":[{"count":9,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/679230\/revisions"}],"predecessor-version":[{"id":683665,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/dotnet\/679230\/revisions\/683665"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/683640"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=679230"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=679230"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=679230"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=679230"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}