avatarMatthew MacDonald

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5638

Abstract

ary constructors</a> is a feature that continues this theme of reducing the amount of hand-written code for common patterns — in this case, constructors. Consider this ordinary class that includes two read-only properties and a constructor:</p><div id="8e7c"><pre><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DataSlice</span> { <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> DataLabel { <span class="hljs-keyword">get</span>; } <span class="hljs-keyword">public</span> <span class="hljs-built_in">float</span> DataValue { <span class="hljs-keyword">get</span>; }

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">DataSlice</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> dataLabel, <span class="hljs-built_in">float</span> dataValue</span>)</span>
{
    DataLabel = dataLabel;
    DataValue = dataValue;
}

}</pre></div><p id="b76f">According to one <a href="https://github.com/dotnet/csharplang/issues/2691">estimate</a>, nearly 75% of their classes have constructors, and 95% of them don’t do anything more than copy parameters into properties, like this example <code>DataSlice</code> class. Constructors like these are so common that it’s no surprise that they eventually collect errors. Assigning a parameter to the wrong property (or to another parameter) is a surprisingly common mistake.</p><p id="b2d6">With a primary constructor, the basic constructor is generated automatically, using constructor arguments that are added to the class declaration. It looks like this:</p><div id="b672"><pre><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-symbol">DataSlice</span>(<span class="hljs-symbol">string</span> <span class="hljs-symbol">dataLabel, <span class="hljs-symbol">float</span></span> <span class="hljs-symbol">dataValue</span>) { ... }</pre></div><p id="72a3">In this example, the <code>dataLabel</code> and <code>dataValue</code> parameters become local private variables that are accessible anywhere in your class code. As long as you use them somewhere (in a property or method), their values are automatically stored with the object. If your intention is simply to provide access through public properties, as in the <code>DataSlice</code> example, you can write your class like this:</p><div id="f348"><pre><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-symbol">DataSlice</span>(<span class="hljs-symbol">string</span> <span class="hljs-symbol">dataLabel, <span class="hljs-symbol">float</span></span> <span class="hljs-symbol">dataValue</span>) { <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> DataLabel { <span class="hljs-keyword">get</span> => dataLabel; } <span class="hljs-keyword">public</span> <span class="hljs-built_in">float</span> DataValue { <span class="hljs-keyword">get</span> => dataValue; }
}</pre></div><p id="df02">Even though you haven’t written any constructor code, you can still create and use the <code>DataSlice</code> class in the same way, using the automatically generated constructor:</p><div id="88c5"><pre><span class="hljs-keyword">var</span> adultData = <span class="hljs-keyword">new</span> <span class="hljs-type">DataSlice</span>(<span class="hljs-string">"Vaccinated adults"</span>, <span class="hljs-number">494</span>);</pre></div><p id="93d8">Using a primary constructor doesn’t preclude property validation. You can still enforce your rules in a property setter, like this:</p><div id="128f"><pre><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DataSlice</span>(<span class="hljs-params"><span class="hljs-built_in">string</span> dataLabel, <span class="hljs-built_in">float</span> dataValue</span>)</span> { <span class="hljs-keyword">public</span> <span class="hljs-built_in">string</span> DataLabel { <span class="hljs-keyword">get</span> => dataLabel; <span class="hljs-keyword">set</span> { <span class="hljs-keyword">if</span> (<span class="hljs-keyword">value</span> < <span class="hljs-number">0</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentOutOfRangeException(); dataLabel = <span class="hljs-keyword">value</span>; } } <span class="hljs-keyword">public</span> <span class="hljs-built_in">float</span> DataValue { <span class="hljs-keyword">get</span> => dataValue; }
}</pre></div><p id="e853">Other details, like adding extra constructors, calling the base constructor in a derived class, and so on, are all possible (and work pretty much the way you would expect, although the feature isn’t formalized yet). The most obvious downside is that primary constructors could collide with positional records, another proposed feature. Follow the ongoing feature discussion <a href="https://github.com/dotnet/csharplang/blob/main/proposals/primary-constructors.md">on GitHub</a> for more.</p><h1 id="d1fe">Raw string literals</h1><p id="80c9">Ordinary C# strings are notoriously messy, because you need to escape quotes (<code>"</code>) and backslashes (<code></code>) and line breaks (<code>\n</code>). C# offers a solution with <i>verbatim strings</i> that allow special characters. Just prefix your string with <code>@</code>, and you get free reign to add all these details, with no escap

Options

ing:</p><div id="1e15"><pre><span class="hljs-comment">// This is awkward</span> <span class="hljs-type">string</span> path = <span class="hljs-string">"c:<span class="hljs-subst">\</span>myfilepath<span class="hljs-subst">\</span>with-backslashes"</span>;</pre></div><div id="4274"><pre>// This <span class="hljs-literal">is</span> better<span class="hljs-built_in"> string</span><span class="hljs-built_in"> path</span> = @<span class="hljs-string">"c:\myfilepath\with-backslashes"</span>;</pre></div><p id="09e4">This approach works well enough for file paths and regular expressions, but it has its own subtle escaping problem. Strings are still delimited with quotation marks, and quotation marks are a common character in code, markup, and regular expressions. That means you can’t stuff any of that type of content into a verbatim string without carefully reviewing it.</p><p id="7473">The <a href="https://github.com/dotnet/csharplang/issues/4304">raw string literal</a> feature creates a new path to sidestep the escaping problem. It uses a new delimiter — a series of quotation marks followed by a line break (to start), and a line break followed by the same number of quotation marks (to end). You just paste your block of code or markup in between.</p><p id="f517">It’s easiest to understand raw strings with an example:</p><div id="3d86"><pre><span class="hljs-built_in">string</span> xml = <span class="hljs-string">""</span><span class="hljs-comment">"</span> <part <span class="hljs-keyword">number</span>=<span class="hljs-string">"1976"</span>> <span class="hljs-symbol"><name></span>Windscreen Wiper</name> <span class="hljs-symbol"><description></span>The Windscreen wiper automatically removes rain from your windscreen. It <span class="hljs-built_in">has</span> <span class="hljs-keyword">a</span> rubber <ref part=<span class="hljs-string">"1977"</span>>blade</ref>, which can <span class="hljs-keyword">be</span> ordered separately. </description> </part> <span class="hljs-string">""</span><span class="hljs-comment">";</span></pre></div><p id="2b13">If you’re concerned that a triple-quotation mark sequence might occur inside your string, you have the option of extending the delimiter to use as many quotation marks as you want, as long as you’re consistent in both the start and the end:</p><div id="7cd1"><pre>string xml = <span class="hljs-string">"""" Now """</span> <span class="hljs-keyword">is</span> safe to <span class="hljs-keyword">use</span> <span class="hljs-keyword">in</span> your raw string. <span class="hljs-string">"""";</span></pre></div><p id="d417">As with <code>@</code> strings, line breaks and whitespace is preserved in a raw string. But there’s one exception. Common whitespace — the amount that’s used to indent the entire example — is trimmed. That means the first example goes from this:</p><div id="8555"><pre> <span class="hljs-tag"><<span class="hljs-name">part</span> <span class="hljs-attr">number</span>=<span class="hljs-string">"1976"</span>></span> <span class="hljs-tag"><<span class="hljs-name">name</span>></span>Windscreen Wiper<span class="hljs-tag"></<span class="hljs-name">name</span>></span> <span class="hljs-tag"><<span class="hljs-name">description</span>></span>The Windscreen wiper automatically removes rain from your windscreen. It has a rubber <span class="hljs-tag"><<span class="hljs-name">ref</span> <span class="hljs-attr">part</span>=<span class="hljs-string">"1977"</span>></span>blade<span class="hljs-tag"></<span class="hljs-name">ref</span>></span>, which can be ordered separately. <span class="hljs-tag"></<span class="hljs-name">description</span>></span> <span class="hljs-tag"></<span class="hljs-name">part</span>></span></pre></div><p id="ee79">To this:</p><div id="1750"><pre><span class="hljs-tag"><<span class="hljs-name">part</span> <span class="hljs-attr">number</span>=<span class="hljs-string">"1976"</span>></span> <span class="hljs-tag"><<span class="hljs-name">name</span>></span>Windscreen Wiper<span class="hljs-tag"></<span class="hljs-name">name</span>></span> <span class="hljs-tag"><<span class="hljs-name">description</span>></span>The Windscreen wiper automatically removes rain from your windscreen. It has a rubber <span class="hljs-tag"><<span class="hljs-name">ref</span> <span class="hljs-attr">part</span>=<span class="hljs-string">"1977"</span>></span>blade<span class="hljs-tag"></<span class="hljs-name">ref</span>></span>, which can be ordered separately. <span class="hljs-tag"></<span class="hljs-name">description</span>></span> <span class="hljs-tag"></<span class="hljs-name">part</span>></span></pre></div><p id="aa00">Raw strings aren’t meant to replace the current <code>@</code> strings you’re using right now. They’re designed for the special case where you need to paste a block of arbitrary code or markup, and you need an approach to encoding that’s guaranteed to be safe.</p><p id="21ca"><i>For more about C#10, get the monthly Young Coder <a href="https://mailchi.mp/45668e72578c/yc">newsletter</a>. And for a stroll down memory lane, read our <a href="https://readmedium.com/c-sharp-language-changes-from-1-0-to-9-0-b2282e8e30fd">write-up</a> on the changes in all 9 versions of C#.</i></p></article></body>

C# 10 — 3 Candidate Features That Could Make the Final Cut

Microsoft’s C# language debate reveals some interesting ideas

UPDATE: C# 10 is now released, and you can get the final word about what made it in — and what didn’t — over here.

One of the perennial benefits of open-source software is being able to watch software projects evolve in real time. The C# language is no exception. You can follow its steady forward march on GitHub, and explore its current set of candidate features.

Now, before we go any deeper into the future of C#, it’s important to note the usual disclaimers. These features are all under active discussion, and there’s no guarantee that C# 10 is the version where they’ll appear. And until they’ve been formally prototyped and specced (most haven’t), there’s plenty of room for them to shift, grow, or even be fused together.

But they aren’t just untethered ideas either. The C# language team sorts potential feature into separate lists, and they’ve explicitly separated ideas that are candidates for the more distant future and ones that aren’t likely to see the light of the day. The ideas in the working set that we’re talking about are all under active consideration. We’d like to see them in C# 10, and with C#’s rapid pace of incremental improvement, the odds are good that they’re within reach.

Many of these ideas continue C#’s drift into the world of functional programming (and we’ll look at those in the near future). But for now, I wanted to highlight three different, promising ideas.

File-level namespaces

Everyone who’s seen even the simplest Hello World program knows that C# uses a block structure for namespaces:

namespace HelloWorld
{
    class Hello
    {         
        static void Main(string[] args)
        {
            System.Console.WriteLine("Hello World!");
        }
    }
}

This approach is admirably flexible. You can layer namespaces just by nesting blocks, a single file can hold types in any combination of namespaces, and multiple files can share the same namespace. The only price we pay for this system is a bit of extra indenting when compared to other curly bracket languages, like Java or JavaScript.

But what if there was a way to get the best of both worlds? In other words, to keep the flexible namespace block, but reduce the excessive indenting in cases when our code fits neatly into one namespace?

Enter file-scoped namespaces, which let you set a default namespace that automatically applies to the entire file, no indenting required:

namespace HelloWorld; 
pubic class Hello
{
    static void Main(string[] args)
    {
        System.Console.WriteLine("Hello World!");
    }
}

You can only have one file-scoped namespace per file, which is fine. The majority of C# code files don’t include multiple namespaces anyway.

If you add a namespace block to a file that uses a file-scoped namespace, it creates a nested namespace, as you would expect:

namespace Company.Product;
// This block creates the namespace Company.Product.Component
namespace Component
{
}

It’s a minor feature, but sometimes easy gains are the best reward.

Primary constructors

In recent releases, C# has taken significant strides in reducing boilerplate code, with features like automatic properties. Despite what new-ish developers sometimes think, these efforts are not simple conveniences. Reducing the amount of code you write reduces the amount of code everyone needs to read. It makes codebases easier to navigate, makes it easier for us to focus on the important logic, and reduces the places where accidents can happen and careless bugs can hide.

Primary constructors is a feature that continues this theme of reducing the amount of hand-written code for common patterns — in this case, constructors. Consider this ordinary class that includes two read-only properties and a constructor:

public class DataSlice
{
    public string DataLabel { get; }
    public float DataValue { get; }
    
    public DataSlice(string dataLabel, float dataValue)
    {
        DataLabel = dataLabel;
        DataValue = dataValue;
    }
}

According to one estimate, nearly 75% of their classes have constructors, and 95% of them don’t do anything more than copy parameters into properties, like this example DataSlice class. Constructors like these are so common that it’s no surprise that they eventually collect errors. Assigning a parameter to the wrong property (or to another parameter) is a surprisingly common mistake.

With a primary constructor, the basic constructor is generated automatically, using constructor arguments that are added to the class declaration. It looks like this:

public class DataSlice(string dataLabel, float dataValue)
{
    ...
}

In this example, the dataLabel and dataValue parameters become local private variables that are accessible anywhere in your class code. As long as you use them somewhere (in a property or method), their values are automatically stored with the object. If your intention is simply to provide access through public properties, as in the DataSlice example, you can write your class like this:

public class DataSlice(string dataLabel, float dataValue)
{
    public string DataLabel { get => dataLabel; }
    public float DataValue { get => dataValue; }    
}

Even though you haven’t written any constructor code, you can still create and use the DataSlice class in the same way, using the automatically generated constructor:

var adultData = new DataSlice("Vaccinated adults", 494);

Using a primary constructor doesn’t preclude property validation. You can still enforce your rules in a property setter, like this:

public class DataSlice(string dataLabel, float dataValue)
{
    public string DataLabel
    {
        get => dataLabel;
        set
        {
            if (value < 0) throw new ArgumentOutOfRangeException();
            dataLabel = value;
        }
    }
    public float DataValue { get => dataValue; }    
}

Other details, like adding extra constructors, calling the base constructor in a derived class, and so on, are all possible (and work pretty much the way you would expect, although the feature isn’t formalized yet). The most obvious downside is that primary constructors could collide with positional records, another proposed feature. Follow the ongoing feature discussion on GitHub for more.

Raw string literals

Ordinary C# strings are notoriously messy, because you need to escape quotes (") and backslashes (\) and line breaks (\n). C# offers a solution with verbatim strings that allow special characters. Just prefix your string with @, and you get free reign to add all these details, with no escaping:

// This is awkward
string path = "c:\\myfilepath\\with-backslashes";
// This is better
string path = @"c:\myfilepath\with-backslashes";

This approach works well enough for file paths and regular expressions, but it has its own subtle escaping problem. Strings are still delimited with quotation marks, and quotation marks are a common character in code, markup, and regular expressions. That means you can’t stuff any of that type of content into a verbatim string without carefully reviewing it.

The raw string literal feature creates a new path to sidestep the escaping problem. It uses a new delimiter — a series of quotation marks followed by a line break (to start), and a line break followed by the same number of quotation marks (to end). You just paste your block of code or markup in between.

It’s easiest to understand raw strings with an example:

string xml = """
          <part number="1976">
            <name>Windscreen Wiper</name>
            <description>The Windscreen wiper automatically removes
             rain from your windscreen. It has a rubber
             <ref part="1977">blade</ref>, which can be ordered
             separately.
            </description>
          </part>
          """;

If you’re concerned that a triple-quotation mark sequence might occur inside your string, you have the option of extending the delimiter to use as many quotation marks as you want, as long as you’re consistent in both the start and the end:

string xml = """" 
             Now """ is safe to use in your raw string.
             """";

As with @ strings, line breaks and whitespace is preserved in a raw string. But there’s one exception. Common whitespace — the amount that’s used to indent the entire example — is trimmed. That means the first example goes from this:

          <part number="1976">
            <name>Windscreen Wiper</name>
            <description>The Windscreen wiper automatically removes
             rain from your windscreen. It has a rubber
             <ref part="1977">blade</ref>, which can be ordered
             separately.
            </description>
          </part>

To this:

<part number="1976">
  <name>Windscreen Wiper</name>
  <description>The Windscreen wiper automatically removes
   rain from your windscreen. It has a rubber
   <ref part="1977">blade</ref>, which can be ordered
   separately.
  </description>
</part>

Raw strings aren’t meant to replace the current @ strings you’re using right now. They’re designed for the special case where you need to paste a block of arbitrary code or markup, and you need an approach to encoding that’s guaranteed to be safe.

For more about C#10, get the monthly Young Coder newsletter. And for a stroll down memory lane, read our write-up on the changes in all 9 versions of C#.

Csharp
Dotnet
Microsoft
Programming
C
Recommended from ReadMedium