<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Miguel Bernard</title>
    <description>The latest articles on Forem by Miguel Bernard (@mbernard).</description>
    <link>https://forem.com/mbernard</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F311057%2F04047b72-3aed-4f70-b694-f0d095a4e63c.png</url>
      <title>Forem: Miguel Bernard</title>
      <link>https://forem.com/mbernard</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mbernard"/>
    <language>en</language>
    <item>
      <title>First and Last line content | Solving the diamond kata with property-based testing</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Mon, 20 Jul 2020 17:19:03 +0000</pubDate>
      <link>https://forem.com/mbernard/first-and-last-line-content-solving-the-diamond-kata-with-property-based-testing-3jhm</link>
      <guid>https://forem.com/mbernard/first-and-last-line-content-solving-the-diamond-kata-with-property-based-testing-3jhm</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;We continue our adventure trying to solve the Diamond Kata while using Property-Based testing. &lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck/"&gt;Last time&lt;/a&gt;, we added our first test, &lt;code&gt;Non-empty&lt;/code&gt; and discovered how to use input generators. Now let's figure out the next test.&lt;/p&gt;

&lt;h1&gt;
  
  
  First and last line content
&lt;/h1&gt;

&lt;p&gt;In the diamond Kata, the first and last line of every diamond always contains &lt;code&gt;A&lt;/code&gt;. Such regularity is perfect for a property. Even the particular case with input &lt;code&gt;A&lt;/code&gt;, where the first line is also the last one, respects that property.&lt;/p&gt;

&lt;p&gt;e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input: A

A
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;input: E

----A----
---B-B---
--C---C--
-D-----D-
E-------E
-D-----D-
--C---C--
---B-B---
----A----
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  C# Tests
&lt;/h1&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Arbitrary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LetterGenerator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;FirstLineContainsA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Diamond&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToProperty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Arbitrary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LetterGenerator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;LastLineContainsA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Diamond&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Last&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'A'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToProperty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here we used some built-in methods of the .NET library, which makes these tests simple to read and short to write. It almost reads like a sentence.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Diamond.Generate(c)&lt;/code&gt; Generates the diamond&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;First() / Last()&lt;/code&gt; Takes the first/last line of the generated diamond&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Contains('A')&lt;/code&gt; Checks if the line contains the letter &lt;code&gt;A&lt;/code&gt; and returns a bool&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ToProperty()&lt;/code&gt; Transforms a boolean expression to a property&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;If you are wondering what's &lt;code&gt;[Property(Arbitrary = new[] { typeof(LetterGenerator) })]&lt;/code&gt; it's probably because you missed my previous &lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck/"&gt;post&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Wrapping up
&lt;/h1&gt;

&lt;p&gt;We are making some good progress towards a fully functioning test suite. However, there are still some uncovered areas that we'll address with more tests &lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;next time&lt;/a&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Input generators in property-based tests with FsCheck</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Fri, 03 Jul 2020 12:04:40 +0000</pubDate>
      <link>https://forem.com/mbernard/input-generators-in-property-based-tests-with-fscheck-11nm</link>
      <guid>https://forem.com/mbernard/input-generators-in-property-based-tests-with-fscheck-11nm</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;Now that we have all the &lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;tools installed&lt;/a&gt;, we are finally ready to write our first Property-Based test.&lt;/p&gt;

&lt;h2&gt;
  
  
  FsCheck
&lt;/h2&gt;

&lt;p&gt;Creating a property-based test is as simple as tagging a method with the &lt;code&gt;[Property]&lt;/code&gt; attribute, similarly as you would do in xUnit with the &lt;code&gt;[Fact]&lt;/code&gt; or &lt;code&gt;[Theory]&lt;/code&gt; attributes. If you dig a little, you will realize that there's a lot of configurable options on the &lt;code&gt;[Property]&lt;/code&gt; attribute. You can control how many random tests will be run each time, timeouts, etc. One of them is essential; the &lt;code&gt;Arbitrary&lt;/code&gt; property. That property will define which method to use to generate random inputs. In our specific case, we are not interested in all the possible values of &lt;code&gt;char&lt;/code&gt;. We only care about the 26 letters of the alphabet. To scope the input, we'll need to configure a generator that will do just that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generators
&lt;/h2&gt;

&lt;p&gt;Generators are relatively simple. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a static class&lt;/li&gt;
&lt;li&gt;Add a static method that returns &lt;code&gt;Arbitrary&amp;lt;TypeYouWantToGenerateValueFor&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Voilà&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;You can write your randomization logic, but it's usually better to start from the built-in methods as they are already well balanced.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LetterGenerator&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Arbitrary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;Arb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="sc"&gt;'A'&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="sc"&gt;'Z'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Not Empty Test
&lt;/h2&gt;

&lt;p&gt;It may seem basic, but it's quite essential. We want to make sure we always have a non-empty result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Arbitrary&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LetterGenerator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;NotEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Diamond&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;All&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToProperty&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;One thing I forgot to mention earlier, the test method also needs to return a &lt;code&gt;property&lt;/code&gt; object.  Fortunately for us, the library contains an extension method that can transform any boolean expression into a property object by calling &lt;code&gt;ToProperty()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So our test reads like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call the &lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/#tdd"&gt;Diamond.Generate()&lt;/a&gt; method with the provided input char &lt;code&gt;c&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Make sure all the lines of the returned diamond are not empty.&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;ToProperty()&lt;/code&gt; method to wrap it into a property object.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stay tuned
&lt;/h2&gt;

&lt;p&gt;Stay tuned for my &lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;next posts&lt;/a&gt; on this &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;series&lt;/a&gt; about solving the diamond kata with property-based testing. The &lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;following post&lt;/a&gt; will try to define properties for the first and last lines of our diamond.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>How to get started with Property-based Testing in C#</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Mon, 29 Jun 2020 18:14:39 +0000</pubDate>
      <link>https://forem.com/mbernard/how-to-get-started-with-property-based-testing-in-c-53me</link>
      <guid>https://forem.com/mbernard/how-to-get-started-with-property-based-testing-in-c-53me</guid>
      <description>&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;So far, we've talked about the benefits of property-based tests in my two previous blog posts &lt;a href="https://blog.miguelbernard.com/whats-wrong-with-the-current-state-of-unit-testing/"&gt;here&lt;/a&gt; and &lt;a href="https://blog.miguelbernard.com/how-many-unit-tests-are-good-enough-property-based-testing/"&gt;here&lt;/a&gt;. I'm sure for most of you; this concept is still pretty abstract. We've seen the technique, but how do we implement it in C#? In this series, we'll go through all the steps to solve the Diamond Kata using TDD and property-based tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Diamond Kata
&lt;/h2&gt;

&lt;p&gt;Given an input letter, print a diamond starting with &lt;code&gt;A&lt;/code&gt; and having the supplied letter at the widest point.&lt;/p&gt;

&lt;p&gt;e.g., For input: D&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nf"&gt;---A---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;--B-B&lt;/span&gt;&lt;span class="nf"&gt;--&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;-C&lt;/span&gt;&lt;span class="nf"&gt;---C-&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;D-----D&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;-C&lt;/span&gt;&lt;span class="nf"&gt;---C-&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;--B-B&lt;/span&gt;&lt;span class="nf"&gt;--&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;---A---&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Why did I choose this specific Kata? Well, if you try to solve it with example-based tests, you effectively need 26 tests to make sure it works properly. It may not seem like a lot of tests, but if you try it, you'll soon discover that the first few tests are trivial, and as you approach &lt;code&gt;Z&lt;/code&gt;, the tests are becoming harder to read and harder to write. It's usually a code smell that indicates that some property-based tests would be a better approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  TDD
&lt;/h2&gt;

&lt;p&gt;In this series, we'll also use TDD, and you'll see that it's much easier to use with Property-based tests than example-based tests. So in excellent TDD practitioners that we are, we are going to start with the most straightforward implementation of the algorithm that we can think of.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Diamond&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Easy, right? It only works for the &lt;code&gt;A&lt;/code&gt; case, but it's a good starting point.&lt;/p&gt;

&lt;p&gt;I already hear the purists among you.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not the right way to do TDD! Red -&amp;gt; Green -&amp;gt; Refactor! You should start with a failing test, not with the implementation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are not wrong, but let's be realistic here. It's just a starting point, and I promise we'll do better TDD going forward :D.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tools
&lt;/h2&gt;

&lt;p&gt;Property-based tests is a simple enough concept, but generating proper pseudo-random inputs can be harder than it looks. Fortunately for us, other people solved that issue and built great tools. In our case, we'll use &lt;a href="https://fscheck.github.io/FsCheck/"&gt;FsCheck&lt;/a&gt;, a property-based testing framework made for F#.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I'm confused, are we doing this in C# or F#?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the beauty of .NET, even though the library is made for F#, all the .NET languages compile to &lt;a href="https://en.wikipedia.org/wiki/Common_Intermediate_Language"&gt;Intermediate Language (IL or MSIL)&lt;/a&gt; and thus are interoperable. It means we can call that library from C#.&lt;/p&gt;

&lt;p&gt;Install the NuGet packages, and you are ready to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nf"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FsCheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.14.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;FsCheck.Xunit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.14.2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing word
&lt;/h2&gt;

&lt;p&gt;I think we have all the prerequisites to get started. Stay tuned for the &lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;next post&lt;/a&gt; where we'll implement our first test.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;a href="https://blog.miguelbernard.com/solving-the-diamond-kata-with-property-based-testing-series/"&gt;Solving the diamond kata with property-based testing series&lt;/a&gt;
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/how-to-get-started-with-property-based-testing-in-csharp/"&gt;How to get started with Property-based Testing in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/input-generators-in-property-based-tests-with-fscheck"&gt;Input generators in property-based tests with FsCheck&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/first-and-last-line-content"&gt;First and Last line content&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/height-equals-width/"&gt;Height equals Width&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/outside-space-symmetry/"&gt;Outside space symmetry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-vertical-axis/"&gt;Symmetry around the vertical axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/symmetry-around-the-horizontal-axis/"&gt;Symmetry around the horizontal axis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/no-padding-for-input-letter-row/"&gt;No padding for input letter row&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/letters-order/"&gt;Letters order&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/property-based-testing"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>testing</category>
      <category>tdd</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>My full MS Build 2020 recap</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 31 May 2020 14:01:17 +0000</pubDate>
      <link>https://forem.com/mbernard/my-full-ms-build-2020-recap-2no3</link>
      <guid>https://forem.com/mbernard/my-full-ms-build-2020-recap-2no3</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;This year was a special edition of MS Build; for obvious reasons, it was 100% virtual. I must say that I had my doubts at first, but I'm forced to admit that Microsoft nailed it. The experience was fantastic. I liked the personal schedule builder and the rebroadcast in 3 different timezones, to only name a few things. Microsoft even took the time to ship the conference's gear to all attendees, DIRECTLY to their doorstep, what a nice touch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2020%2F05%2FIMG_0293.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2020%2F05%2FIMG_0293.jpg" alt="IMG_0293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There were over 600 sessions, running 24h/day continuously. Unfortunately, this recap only covers what I was able to watch. If you see something missing, don't hesitate to engage in the comments down below.&lt;/p&gt;

&lt;h1&gt;
  
  
  Recap
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/23912de2-1531-4684-b85a-d57ac30af09e" rel="noopener noreferrer"&gt;Empowering every developer, with Satya Nadella&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Once again, Satya had a very compelling opening keynote. He remembered everyone that in a world constantly changing, the developer is more important than ever. Microsoft is building the best toolchain to empower those developers. &lt;/p&gt;

&lt;p&gt;No big announcements from his part, but he highlighted some critical aspects of the conference to keep on eye on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;VSCode&lt;/li&gt;
&lt;li&gt;PowerPlatform&lt;/li&gt;
&lt;li&gt;Azure&lt;/li&gt;
&lt;li&gt;O365&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/871ef73f-f04a-405b-a0fa-01d7433067d1" rel="noopener noreferrer"&gt;Every developer is welcome, with Scott Hanselman and guests&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Scott was demoing some new vital tools in the developer environment, starting at the workstation's tooling. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://devblogs.microsoft.com/commandline/windows-package-manager-preview/" rel="noopener noreferrer"&gt;Winget&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Winget is a new tool to manage and script the installation of software packages. It will save developers a ton of time when they need to rebuild or set up their machines for a new project.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/microsoft/PowerToys" rel="noopener noreferrer"&gt;PowerToys&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;He showed some of the features of &lt;a href="https://github.com/microsoft/PowerToys" rel="noopener noreferrer"&gt;PowerToys&lt;/a&gt;, namely fancy zones, which I must admit is pretty awesome to arrange your working space in a more efficient way.&lt;/p&gt;

&lt;h3&gt;
  
  
  WSL 2.0
&lt;/h3&gt;

&lt;p&gt;WSL 2.0 now support graphical applications, and there's even a new Linux file explorer GUI available.&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows terminal
&lt;/h3&gt;

&lt;p&gt;Windows terminal is finally out of beta and just hit version 1.0.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="//aka.ms/codespaces"&gt;CodeSpaces&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Developing applications has always been made working locally. This approach comes with some downsides. For instance, you need to have all the tools and other dependencies of the project installed locally. It tends to create snowflakes environment. How many times have you heard "Strange it works on my machine". &lt;/p&gt;

&lt;p&gt;Microsoft is coming with a new developer experience that runs entirely remotely. &lt;a href="//aka.ms/codespaces"&gt;CodeSpaces&lt;/a&gt; (formerly VS online) is a new tool that enables you to spin a complete dev environment in the cloud, on a remote machine. Then you can develop directly in your browser or connect to it with your favorite tools like VS Code or Visual Studio. &lt;/p&gt;

&lt;p&gt;It's also now possible to spin up a fully functioning environment &lt;a href="//github.com/features/codespaces"&gt;from a GitHub repository&lt;/a&gt;. It will come pretty handly to review a pull request. &lt;/p&gt;

&lt;p&gt;Collaboration is at the heart of this new experience. With LiveShare, you can collaborate with multiple people on that remote environment like you would in an Office document. This functionality will enable a whole new way of doing pair programming, mainly since most of us are still confined at home.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/80ec2639-35c3-462b-8155-1ef52c29310c" rel="noopener noreferrer"&gt;Azure: Invent with Purpose&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;That session started with some impressive statistics about the Microsoft Intelligent Cloud (a.k.a. Azure + O365).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used by 95% of Fortune 500 companies&lt;/li&gt;
&lt;li&gt;61 azure regions, more than any other cloud provider&lt;/li&gt;
&lt;li&gt;MS Teams hosts 4.1 billion meeting minutes per day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are some pretty impressive numbers, and it seems they keep growing quarter after quarter. All of these remarkable services are built on top of the same building blocks that are publically available to you in Azure; ServiceFabric, Kuberbernates, Media Services, Redis, FrontDoor, etc. &lt;/p&gt;

&lt;p&gt;Microsoft wants to enable all the developers to focus on their application and not on the infrastructure supporting it. Speaking of which, they announced some new capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AKS
Windows container support for lift and shift scenarios
Spot pricing for low priority workloads&lt;/li&gt;
&lt;li&gt;ComosDB
A free tier that gives you 400 RU
Serverless pricing where you only pay per consumption
Auto-scale&lt;/li&gt;
&lt;li&gt;AI
New cognitive services&lt;/li&gt;
&lt;li&gt;Synapse
Synapse Link for real-time data analytics with no performance impacts on operational DB
No ETL required
Deep integration with PowerBI&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/dc9d0a63-4a90-48bc-925f-6847745eba7b" rel="noopener noreferrer"&gt;The Journey to One .NET&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;First of all, there's a new kid on the block, Blazor WASM, which brings a new alternative for devs to run .NET in the browser to build rich client applications using the technology they know. It provides complete debugging capabilities in the browser. It's also possible to debug a full loop of Front-end and Back-end altogether in Visual Studio.&lt;/p&gt;

&lt;p&gt;It's the beginning of the unification of the whole .NET stack. &lt;br&gt;
Dotnet Core and Framework will be merged in the new version .NET 5. &lt;br&gt;
MAUI will be the evolution of Xamarin Forms and will bring a single UI that can target any platform like Android, iPhone, Windows, etc.&lt;/p&gt;

&lt;p&gt;Complete talk &lt;a href="https://aka.ms/dotnetjourney" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/61cbcae3-b5a5-4ddb-acd4-fe80117d5112" rel="noopener noreferrer"&gt;C# Today &amp;amp; Tomorrow&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I think that session was my favorite. I must admit I'm a big fan of Functional Programming (FP) and especially F#. Microsoft showed some preview of what's coming in C# 9.0. Most of the new features are all about FP concepts and are implemented very similarly to F#, which will help bridge the gap between the two languages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutability in C# classes&lt;/li&gt;
&lt;li&gt;Simplicity, you can now skip some boilerplate code like &lt;code&gt;Program.cs&lt;/code&gt; and the &lt;code&gt;Main&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;Structural equality&lt;/li&gt;
&lt;li&gt;Better pattern matching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all of this, Microsoft will reach an even broader audience and onboard them in the rich ecosystem of C#. It will also provide all the necessary tools for C# developers to start playing with FP concepts and write better code.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/6d41f15c-aff0-42a6-ba45-46eb73ec41eb" rel="noopener noreferrer"&gt;Making every developer and team more productive from dev box setup to coding to deployment and debugging&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Microsoft has always invested a lot in great tooling. Call me a fanboy, but Visual Studio and VS Code are, in my opinion, the two best IDE out there. They are now bringing an improved experience within collaborative development with chat and voice integration directly in LiveShare. Git support also got a significant revamp, improving how VS handles git repositories. IntelliCode got smarter; it's now able to suggest coding standards that your teammates are following. It will save a lot of comments in PR when onboarding new developers in a project. &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/c09c7e2b-d60a-496d-beb6-bbaa79aa0a5e" rel="noopener noreferrer"&gt;Infrastructure as code - build Azure applications with ARM templates&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Code (IaC) is the new trend in DevOps practices, and Microsoft knows it. They are doubling down in their IaC technology, the ARM Templates. They added a useful new parameter that you can use in PowerShell or Azure CLI when deploying an ARM template. &lt;code&gt;What-if&lt;/code&gt; will output all the changes that will be executed if you deploy that ARM Template. A great feature to validate impacts before deploying. There are also some new features to ARM template themselves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-generation of parameter files&lt;/li&gt;
&lt;li&gt;Intellisense for &lt;code&gt;ResourceId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Improved schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microsoft added &lt;code&gt;TemplateSpec&lt;/code&gt;, a new way to package, version, and store ARM templates. It will help simplify the deployment of big infrastructures.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/6c6ecd46-c39c-49d8-baed-3bc207bc5bec" rel="noopener noreferrer"&gt;The future of tech, with Kevin Scott and guests&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Microsoft has built one of the biggest supercomputers on earth (Top 5), putting it at the service of AI for everyone's benefit. They are improving their models and offering it to you as a service. They are also running a lot of research projects on it. &lt;/p&gt;

&lt;p&gt;In that session, they showed an AI that can automatically read a user requirement and write Python code that fulfills that requirement. What's impressive is that the generated code integrates flawlessly with existing code. Not only the code is accurate, but it's well written and easy to read. It's utterly indistinguishable from code written by a real person. I don't think this kind of capability will ever replace a good old developer, but it can indeed be an excellent tool to have to speed up the development of an application.&lt;/p&gt;

&lt;p&gt;Microsoft is one of the few providers that brings the AI at the edge. It enables the use of AI in the most challenging environments that don't always have a stable internet connection. On one of the demos, the equip a robot from Boston Robotics to make it fully autonomous.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/4b904963-a22a-4046-b01b-85eb2c1f9732" rel="noopener noreferrer"&gt;Accelerating enterprise app development with Power Platform&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The Power platform is having a lot of traction lately. It allows super rapid application development, which requires little to no code at all. It's currently used by more than 97% of the Fortune 500. This rich environment of tools for power users is also adding new services. Power Virtual Agent is a new automated chatbot build on top of the Microsoft bot framework.&lt;/p&gt;




&lt;h2&gt;
  
  
  Other notable improvements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/279676e7-2c9b-4209-a070-b393812bae16" rel="noopener noreferrer"&gt;ApplicationInsights &amp;amp; Azure Monitor&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Support for the OpenTelemetry standard&lt;/li&gt;
&lt;li&gt;Transaction correlation support for Azure Service Bus&lt;/li&gt;
&lt;li&gt;New visualization&lt;/li&gt;
&lt;li&gt;Merge of application and infrastructure logs for better correlation and diagnostics capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/d8589a91-ae83-43f3-b522-f152aee2f031" rel="noopener noreferrer"&gt;Azure SQL&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Serverless option, only pay for what you use&lt;/li&gt;
&lt;li&gt;Scale instantly&lt;/li&gt;
&lt;li&gt;Can event completely pause/resume your DB automatically (e.g., at night when there's no traffic)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://mybuild.microsoft.com/sessions/17e87279-4742-4a36-b5d5-73240141648e" rel="noopener noreferrer"&gt;Azure Databricks and Sparks&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AAD authentication&lt;/li&gt;
&lt;li&gt;DataBricks pools&lt;/li&gt;
&lt;li&gt;DataBricks container services&lt;/li&gt;
&lt;li&gt;ZSkipping, a new algorithm that can bring up to 100x performance improvement&lt;/li&gt;
&lt;li&gt;DeltaLake&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Closing
&lt;/h1&gt;

&lt;p&gt;It does not entirely cover the event, but it should give you a good overview of the significant announcements. Thank you again, Microsoft, for organizing such a great online and free event.&lt;/p&gt;

&lt;p&gt;You can also consult &lt;a href="https://news.microsoft.com/build-2020-book-of-news/" rel="noopener noreferrer"&gt;the official book of news&lt;/a&gt; for the complete list of announcements.&lt;/p&gt;

</description>
      <category>msbuild</category>
      <category>azure</category>
      <category>microsoft</category>
      <category>o365</category>
    </item>
    <item>
      <title>You need these tools to be more efficient at Testing with AutoFixture and FakeItEasy</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Tue, 05 May 2020 15:22:04 +0000</pubDate>
      <link>https://forem.com/mbernard/you-need-these-tools-to-be-more-efficient-at-testing-with-autofixture-and-fakeiteasy-40a3</link>
      <guid>https://forem.com/mbernard/you-need-these-tools-to-be-more-efficient-at-testing-with-autofixture-and-fakeiteasy-40a3</guid>
      <description>&lt;p&gt;There are many well-known benefits of testing your code, but for many developers, testing is still the part of their job they like the least. They find it hard and painful, but it doesn't have to be that way. &lt;br&gt;
Nowadays, there's excellent tooling to make it fun and productive, and that's what this blog post is all about.&lt;/p&gt;

&lt;p&gt;xUnit, AutoFixture, and FakeItEasy are among my favorites frameworks/tools. They all achieve something particular, and they all play well together. I won't go over the details for each one, because there's a ton of documentation with great examples out there, but here's a quick look at what they do.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://xunit.github.io/"&gt;xUnit&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;xUnit.net is a free, open-source, community-focused unit testing tool for the .NET Framework. Written by the original inventor of NUnit v2, xUnit.net is the latest technology for unit testing C#, F#, VB.NET, and other .NET languages. xUnit.net works with ReSharper, CodeRush, TestDriven.NET, and Xamarin.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://github.com/AutoFixture/AutoFixture"&gt;AutoFixture&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;AutoFixture is an open-source library for .NET designed to minimize the 'Arrange' phase of your unit tests to maximize maintainability. Its primary goal is to allow developers to focus on what is being tested rather than how to set up the test scenarios by making it easier to create object graphs containing test data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://fakeiteasy.github.io/"&gt;FakeItEasy&lt;/a&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;FakeItEasy is a .Net dynamic fake framework for creating all types of fake objects, mocks, stubs, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, what I'm more interested in is to show you how to integrate them. Let's do it with a hands-on example that we're going to complete together.&lt;/p&gt;

&lt;p&gt;First of all, install the following NuGet packages in your test project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;xunit&lt;/li&gt;
&lt;li&gt;AutoFixture&lt;/li&gt;
&lt;li&gt;FakeItEasy&lt;/li&gt;
&lt;li&gt;AutoFixture.Xunit2&lt;/li&gt;
&lt;li&gt;AutoFixture.FakeItEasy&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Class to test
&lt;/h2&gt;

&lt;p&gt;Second of all, let's define a simple example of a class to test a.k.a. System Under Test (sut)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StringService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;INumberService&lt;/span&gt; &lt;span class="n"&gt;_service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;StringService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INumberService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;ConvertToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Service that returns a number for each char in a string&lt;/span&gt;
        &lt;span class="c1"&gt;// corresponding to that letter position in the alphabet&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Test - V1
&lt;/h2&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Theory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"def"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GivenAString_WhenConvertToNumber_ThenSumOfLetterPositionIsReturned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Given&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fake&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;INumberService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CallTo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;StringService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// When&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConvertToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Then&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Pretty simple, it's neither too big nor dirty. We are leveraging &lt;code&gt;[Theory] and [InlineData]&lt;/code&gt; to get a helpful, clean test, but it seems like we might miss some test cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test - V2
&lt;/h2&gt;

&lt;p&gt;Let's change the test to use &lt;code&gt;[AutoData]&lt;/code&gt; in order to generate random test data and cover more edge cases&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Theory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AutoData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineAutoData&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineAutoData&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"def"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GivenAString_WhenConvertToNumber_ThenSumOfLetterPositionIsReturned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Given&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fixture&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Fixture&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fake&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;INumberService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CallTo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;INumberService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(()=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;StringService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// When&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConvertToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Then&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It's nice to have some auto-generated test data, but the Given part of the test is getting quite big and harder to understand. We can probably do something with this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test - Final Version
&lt;/h2&gt;

&lt;p&gt;Let's use everything in the toolbox, but to do so, we'll need to create our integration between the frameworks.&lt;/p&gt;

&lt;p&gt;Here's the actual implementation of the &lt;code&gt;[AutoDataFakeItEasy]&lt;/code&gt; and &lt;code&gt;[InlineAutoDataFakeItEasy]&lt;/code&gt; attributes that will make all of the heavy lifting for you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Magic Attributes
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;AttributeUsage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AttributeTargets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AutoFakeItEasyDataAttribute&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AutoDataAttribute&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AutoFakeItEasyDataAttribute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FixtureFactory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IFixture&lt;/span&gt; &lt;span class="nf"&gt;FixtureFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Fixture&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Customize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AutoFakeItEasyCustomization&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;AttributeUsage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AttributeTargets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AllowMultiple&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InlineAutoFakeItEasyDataAttribute&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InlineAutoDataAttribute&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;_values&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;InlineAutoFakeItEasyDataAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;params&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AutoFakeItEasyDataAttribute&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;]&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MethodInfo&lt;/span&gt; &lt;span class="n"&gt;testMethod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;testMethod&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  The final test
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Theory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AutoDataFakeItEasy&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineAutoDataFakeItEasy&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;InlineAutoDataFakeItEasy&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GivenAString_WhenConvertToNumber_ThenSumOfLetterPositionIsReturned&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Frozen&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;INumberService&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringService&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Given&lt;/span&gt;
    &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CallTo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;.&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// When&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sut&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConvertToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Then&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;charValues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sum&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We still get all the benefits of auto-generated test data and the flexibility to add our specific test cases. The best part, we got rid of all the boilerplate code that was initializing our sut and its dependencies. The attributes will make sure to initialize our test values with inputs from the attribute or random data otherwise. They'll then make sure to instantiate mocks and dummy classes, also taking care of all their dependencies. It gives us a very robust and maintainable test that will survive many refactors without needing any changes.&lt;/p&gt;

&lt;p&gt;The only thing we need to define now is the behavior of the mock, calling the method under test and asserting the result. Wow, this is what every test should look like. Like we say: less is more.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;It is a very simple sut and test. Imagine when you have a complex class to test, how much code and complexity you can save with these attributes.&lt;br&gt;
As you can see, knowing the right tools can make you super efficient at writing good unit tests. Moreover, your tests will be simple to understand and maintain over time.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>testing</category>
      <category>csharp</category>
      <category>unittesting</category>
    </item>
    <item>
      <title>Why null in C# is so bad</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 26 Apr 2020 13:49:00 +0000</pubDate>
      <link>https://forem.com/mbernard/why-null-in-c-is-so-bad-cid</link>
      <guid>https://forem.com/mbernard/why-null-in-c-is-so-bad-cid</guid>
      <description>&lt;p&gt;In my career, more than half of the bugs I encountered were related in a way or another to a null value being propagated where it shouldn't have been—therefore resulting in unexpected behaviors or a nasty &lt;code&gt;NullReferenceException&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;Why is null such a problem in C#? Well... the null problem (a.k.a the billion-dollar mistake) breaks many assumptions you can make about the programming language. &lt;/p&gt;

&lt;p&gt;In more theoretical terms, it breaks the Liskov substitution principle. (One of the famous &lt;a href="https://en.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID principles&lt;/a&gt;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let Φ(x) be a property provable about objects x of type T. Then Φ(y)should be true for objects y of type S where S is a subtype of T.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2019%2F03%2FlB5wmMp-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2019%2F03%2FlB5wmMp-1.png" alt="lB5wmMp-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Did I lose you? Great! Now let's talk plain English.
&lt;/h4&gt;

&lt;p&gt;It means that you should be able to use any subtype in place of its parent type without affecting the behavior of the application. &lt;/p&gt;

&lt;h4&gt;
  
  
  What does that have to do with null?
&lt;/h4&gt;

&lt;p&gt;In the C# compiler, there's a rule to enforce and prevent multiple inheritances... except... for null. Null is a special instruction in the language that can substitute any type. Put in another way; it means that null inherits from all reference types.&lt;/p&gt;

&lt;p&gt;Because of that, you cannot think of your code logically anymore. You always have to check if the value is of subtype null or not. You have to check this because null behave in a very different way than any other type. It needs special processing and/or logic branching.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_customerRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// rest of the logic here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// logic for the null case here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This practice, often referenced as defensive programming, makes your code verbose and error-prone. It works fine-ishhh. To make it work, you need to do it everywhere in your system. It's really easy to forget one location and guess what? It's precisely where you're going to get a &lt;code&gt;NullReferenceException&lt;/code&gt; popping up in production.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solutions
&lt;/h1&gt;

&lt;p&gt;Yes, of course, you can use the more beautiful Elvis operator &lt;code&gt;?.&lt;/code&gt;, but it doesn't solve anything. It just makes the code more readable.&lt;/p&gt;

&lt;p&gt;The only real solution is to get rid of all the &lt;code&gt;null&lt;/code&gt;. That being said, unless you have very strict coding rules within your team, I doubt you'll be able to do it. It's always tempting as a developer to take a shortcut and return a null value on a function call.&lt;/p&gt;

&lt;h3&gt;
  
  
  C# 8.0 to the rescue
&lt;/h3&gt;

&lt;p&gt;Fortunately, C# 8.0 adds a brand new &lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/" rel="noopener noreferrer"&gt;feature&lt;/a&gt; to help us with the &lt;code&gt;null&lt;/code&gt; witch hunt. That new option instructs the compiler to check for null values in all code paths. Simply add this line to your &lt;code&gt;.csproj&lt;/code&gt; and voilà!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;Nullable&amp;gt;&lt;/span&gt;enable&lt;span class="nt"&gt;&amp;lt;/Nullable&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2019%2F03%2Fvs_csharp_null_warning.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.miguelbernard.com%2Fcontent%2Fimages%2F2019%2F03%2Fvs_csharp_null_warning.png" alt="vs_csharp_null_warning"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can start getting rid of those null values and make sure nobody introduces new ones behind your back.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Using that will most likely break everything on a brownfield project, but for greenfield projects, I highly recommend you enable it. It might seem more work at first, but writing code without passing null around will save you many long, painful debugging hours in production. Ask me how I know. For me, that upfront development cost is a no-brainer.&lt;/p&gt;

&lt;p&gt;Good hunt!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>aspnet</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>How to backup your Azure Storage Accounts</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 19 Apr 2020 15:03:33 +0000</pubDate>
      <link>https://forem.com/mbernard/how-to-backup-your-azure-storage-accounts-34g9</link>
      <guid>https://forem.com/mbernard/how-to-backup-your-azure-storage-accounts-34g9</guid>
      <description>&lt;p&gt;Azure Storage Account is one of the foundation services of Azure. Pretty much all other services use it under the cover in a way or another. This service is simple, works great, and has crazy SLA and redundancy capabilities. However, it doesn't provide a point in time restore. Meaning that if you corrupt or delete some data, there's no way to recover it. There are some solutions that you can find over the internet, but unfortunately, none of them is a silver bullet. Let's explore and compare some of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;Let's first define some goals and requirements before we jump into solutions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Backups must run on a schedule (e.g., every hour)&lt;/li&gt;
&lt;li&gt;Backups must be fast&lt;/li&gt;
&lt;li&gt;Minimize network traffic $$$&lt;/li&gt;
&lt;li&gt;The solution must be easy to maintain and operate&lt;/li&gt;
&lt;li&gt;Get notification or report on failures&lt;/li&gt;
&lt;li&gt;Must support multi-environment configuration (dev, QA, prod, etc...)&lt;/li&gt;
&lt;li&gt;Has support for both Blob and Table storage format&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  AzCopy
&lt;/h3&gt;

&lt;p&gt;AzCopy is a great tool to move data around in Azure, and it's also what most people will suggest using for backups. Target a source and a destination backup storage account and voilà! The AzCopy command-line performs the processing of that operation inside Azure datacenter between the two target storage accounts instead of passing by the machine that runs AzCopy. This feature alone makes AzCopy an obvious choice as it covers 2 of the most important objectives:&lt;br&gt;
No. 2: Backup must be fast&lt;br&gt;
No. 3: Minimize network traffic $$$&lt;br&gt;
That's why most backup solutions use this tool.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution 1: Running from your PC
&lt;/h2&gt;

&lt;p&gt;AzCopy is a command-line tool, so it's pretty easy to run from your machine or an on-prem server to backup your storage accounts. You can create a windows schedule to run that command, and you are good to go. It works fine when you have a few storage accounts, but grows complex real fast when adding more storage.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to set up and automate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No easy way to get notified on a failure&lt;/li&gt;
&lt;li&gt;Not easy to set it up for multiple environments&lt;/li&gt;
&lt;li&gt;Scalability&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Solution 2: Azure Automation
&lt;/h2&gt;

&lt;p&gt;Azure Automation allows you to run PowerShell script directly in Azure. With that service, you can easily create a script that launches AzCopy with the specified arguments to target your storage accounts.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to set up a schedule&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Not that simple to install a .exe and run it on their hosted agent (You need to run it with a Hybrid Runbook Worker)&lt;/li&gt;
&lt;li&gt;Not easy to set it up for multiple environments&lt;/li&gt;
&lt;li&gt;No notification on failures&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Solution 3: Let's try thinking outside the box
&lt;/h2&gt;

&lt;p&gt;What about using Azure DevOps? It seems crazy right, but let's look at it more closely. One of the common problems with previous solutions is the management of backups for multiple environments and notifications on failure. Another problem is to install AzCopy on the agent or machine that's going to run the backup. Good news though, AzCopy is already installed by default on all Azure DevOps agents.&lt;br&gt;
So here's a general idea: Create a pipeline that runs on a schedule and performs backup for each environment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a PowerShell module with utility methods to make the use of AzCopy easier and upload it to your git repository&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;EDIT: You can now download all these scripts from &lt;a href="https://github.com/mbernard/AzureUtils"&gt;Github&lt;/a&gt;. Also, special thanks to my good friend &lt;a href="https://github.com/yohanb"&gt;Yohan&lt;/a&gt; who cleaned up the whole thing and added the restore functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Backup-Storage-Accounts.psm1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Build-AzCopyCmd&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;PSCustomObject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;PSCustomObject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$AzCopyParam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SourcePath&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccountKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StorageAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Credentials&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportBase64EncodedKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;$destStorageAccountKey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StorageAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Credentials&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExportBase64EncodedKey&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;$destContainer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StorageAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateCloudBlobClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetContainerReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="nf"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""{0}"" /source:{1} /dest:{2} /sourcekey:""{3}"" 
      /destkey:""{4}"" &lt;/span&gt;&lt;span class="nv"&gt;$AzCopyParam&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Program Files (x86)\Microsoft 
      SDKs\Azure\AzCopy\AzCopy.exe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SourcePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$destContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AbsoluteUri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
      &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccountKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$destStorageAccountKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Invoke-AzCopyCmd&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$AzCopyCmd&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$AzCopyCmd&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$LASTEXITCODE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;Write-Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Copy failed!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Copy succeed!"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nf"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-----------------"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Backup-Blobs&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;PSCustomObject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;PSCustomObject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Mandatory&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageContainers&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="kr"&gt;Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageContainers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'*$*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nf"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-----------------"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nf"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Skipping copy: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"
        Write-Host "&lt;/span&gt;&lt;span class="nf"&gt;-----------------&lt;/span&gt;&lt;span class="s2"&gt;"
        Continue;
      }

      Write-Host "&lt;/span&gt;&lt;span class="nf"&gt;-----------------&lt;/span&gt;&lt;span class="s2"&gt;"
      Write-Host "&lt;/span&gt;&lt;span class="nx"&gt;Start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;copying:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"
      Write-Host "&lt;/span&gt;&lt;span class="nf"&gt;-----------------&lt;/span&gt;&lt;span class="s2"&gt;"

      &lt;/span&gt;&lt;span class="nv"&gt;$blobDestinationPath&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="s2"&gt; + "&lt;/span&gt;&lt;span class="nx"&gt;/blobs/&lt;/span&gt;&lt;span class="s2"&gt;" + &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="s2"&gt;.Name
      &lt;/span&gt;&lt;span class="nv"&gt;$azCopyParam&lt;/span&gt;&lt;span class="s2"&gt; = "&lt;/span&gt;&lt;span class="nx"&gt;/snapshot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/synccopy&lt;/span&gt;&lt;span class="s2"&gt;"
      &lt;/span&gt;&lt;span class="nv"&gt;$sourcePath&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageContainer&lt;/span&gt;&lt;span class="s2"&gt;.CloudBlobContainer.Uri.AbsoluteUri
      &lt;/span&gt;&lt;span class="nv"&gt;$azCopyCmd&lt;/span&gt;&lt;span class="s2"&gt; = Build-AzCopyCmd -DestinationPath &lt;/span&gt;&lt;span class="nv"&gt;$blobDestinationPath&lt;/span&gt;&lt;span class="s2"&gt; -SrcCtx
          &lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt; -DestCtx &lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="s2"&gt; -AzCopyParam &lt;/span&gt;&lt;span class="nv"&gt;$azCopyParam&lt;/span&gt;&lt;span class="s2"&gt; -SourcePath 
          &lt;/span&gt;&lt;span class="nv"&gt;$sourcePath&lt;/span&gt;&lt;span class="s2"&gt;
      Invoke-AzCopyCmd -AzCopyCmd &lt;/span&gt;&lt;span class="nv"&gt;$AzCopyCmd&lt;/span&gt;&lt;span class="s2"&gt;
    }
  }
}

function Backup-Tables 
{
  param(
    [Parameter(Mandatory)] 
    [string]&lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="s2"&gt;,
    [Parameter(Mandatory)] 
    [PSCustomObject]&lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt;,
    [Parameter(Mandatory)] 
    [PSCustomObject]&lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="s2"&gt;,
    [Parameter(Mandatory)]
    [array] &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageTables&lt;/span&gt;&lt;span class="s2"&gt;
  )

  Process {
    foreach (&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageTable&lt;/span&gt;&lt;span class="s2"&gt; in &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageTables&lt;/span&gt;&lt;span class="s2"&gt;)
    {
      Write-Host "&lt;/span&gt;&lt;span class="nf"&gt;-----------------&lt;/span&gt;&lt;span class="s2"&gt;"
      Write-Host "&lt;/span&gt;&lt;span class="nx"&gt;Start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;copying:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageTable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"
      Write-Host "&lt;/span&gt;&lt;span class="nf"&gt;-----------------&lt;/span&gt;&lt;span class="s2"&gt;"

      &lt;/span&gt;&lt;span class="nv"&gt;$tableDestinationPath&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$DestinationPath&lt;/span&gt;&lt;span class="s2"&gt; + "&lt;/span&gt;&lt;span class="nx"&gt;/tables/&lt;/span&gt;&lt;span class="s2"&gt;" + &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageTable&lt;/span&gt;&lt;span class="s2"&gt;.Name
      &lt;/span&gt;&lt;span class="nv"&gt;$azCopyParam&lt;/span&gt;&lt;span class="s2"&gt; = "&lt;/span&gt;&lt;span class="nx"&gt;/y&lt;/span&gt;&lt;span class="s2"&gt;"
      &lt;/span&gt;&lt;span class="nv"&gt;$sourcePath&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageTable&lt;/span&gt;&lt;span class="s2"&gt;.CloudTable.Uri.AbsoluteUri        
      &lt;/span&gt;&lt;span class="nv"&gt;$azCopyCmd&lt;/span&gt;&lt;span class="s2"&gt; = Build-AzCopyCmd -DestinationPath &lt;/span&gt;&lt;span class="nv"&gt;$tableDestinationPath&lt;/span&gt;&lt;span class="s2"&gt; -SrcCtx
          &lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt; -DestCtx &lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="s2"&gt; -AzCopyParam &lt;/span&gt;&lt;span class="nv"&gt;$azCopyParam&lt;/span&gt;&lt;span class="s2"&gt; -SourcePath 
          &lt;/span&gt;&lt;span class="nv"&gt;$sourcePath&lt;/span&gt;&lt;span class="s2"&gt;
      Invoke-AzCopyCmd -AzCopyCmd &lt;/span&gt;&lt;span class="nv"&gt;$AzCopyCmd&lt;/span&gt;&lt;span class="s2"&gt;
    }
  }
}

function Backup-StorageAccount
{
  param(
    [Parameter(Mandatory)] 
    [PSCustomObject]&lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt;,
    [Parameter(Mandatory)] 
    [PSCustomObject]&lt;/span&gt;&lt;span class="nv"&gt;$DestCtx&lt;/span&gt;&lt;span class="s2"&gt;
  )

  &lt;/span&gt;&lt;span class="nv"&gt;$currentDate&lt;/span&gt;&lt;span class="s2"&gt; = (Get-Date).ToUniversalTime().tostring('yyyy\/MM\/dd\/HH:mm')
  &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageAccountName&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$srcCtx&lt;/span&gt;&lt;span class="s2"&gt;.StorageAccount.Credentials.AccountName
  &lt;/span&gt;&lt;span class="nv"&gt;$destinationPath&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$SrcStorageAccountName&lt;/span&gt;&lt;span class="s2"&gt; + "&lt;/span&gt;&lt;span class="nx"&gt;/&lt;/span&gt;&lt;span class="s2"&gt;" + &lt;/span&gt;&lt;span class="nv"&gt;$currentDate&lt;/span&gt;&lt;span class="s2"&gt;    

  &lt;/span&gt;&lt;span class="nv"&gt;$srcTables&lt;/span&gt;&lt;span class="s2"&gt; = Get-AzureStorageTable -Context &lt;/span&gt;&lt;span class="nv"&gt;$srcCtx&lt;/span&gt;&lt;span class="s2"&gt;

  if(&lt;/span&gt;&lt;span class="nv"&gt;$srcTables&lt;/span&gt;&lt;span class="s2"&gt;)
  {
    Backup-Tables -DestinationPath &lt;/span&gt;&lt;span class="nv"&gt;$destinationPath&lt;/span&gt;&lt;span class="s2"&gt; -SrcCtx &lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt; 
        -DestCtx &lt;/span&gt;&lt;span class="nv"&gt;$destCtx&lt;/span&gt;&lt;span class="s2"&gt; -SrcStorageTables &lt;/span&gt;&lt;span class="nv"&gt;$srcTables&lt;/span&gt;&lt;span class="s2"&gt;
  }

  &lt;/span&gt;&lt;span class="nv"&gt;$maxReturn&lt;/span&gt;&lt;span class="s2"&gt; = 250
  &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="s2"&gt;

  do{      
    &lt;/span&gt;&lt;span class="nv"&gt;$srcContainers&lt;/span&gt;&lt;span class="s2"&gt; = Get-AzureStorageContainer -MaxCount &lt;/span&gt;&lt;span class="nv"&gt;$maxReturn&lt;/span&gt;&lt;span class="s2"&gt; 
        -ContinuationToken &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt; -Context &lt;/span&gt;&lt;span class="nv"&gt;$srcCtx&lt;/span&gt;&lt;span class="s2"&gt;

    if(&lt;/span&gt;&lt;span class="nv"&gt;$srcContainers&lt;/span&gt;&lt;span class="s2"&gt;)
    {
      &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="nv"&gt;$srcContainers&lt;/span&gt;&lt;span class="s2"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$srcContainers&lt;/span&gt;&lt;span class="s2"&gt;.Count -1].ContinuationToken;
      Backup-Blobs -DestinationPath &lt;/span&gt;&lt;span class="nv"&gt;$destinationPath&lt;/span&gt;&lt;span class="s2"&gt; -SrcCtx &lt;/span&gt;&lt;span class="nv"&gt;$SrcCtx&lt;/span&gt;&lt;span class="s2"&gt; -DestCtx
          &lt;/span&gt;&lt;span class="nv"&gt;$destCtx&lt;/span&gt;&lt;span class="s2"&gt; -SrcStorageContainers &lt;/span&gt;&lt;span class="nv"&gt;$srcContainers&lt;/span&gt;&lt;span class="s2"&gt;
    }
  }
  While (&lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt; -ne &lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="s2"&gt;)
}

function Get-StorageAccountContext 
{
  param(
    [Parameter(Mandatory)] 
    [string]&lt;/span&gt;&lt;span class="nv"&gt;$StorageAccountName&lt;/span&gt;&lt;span class="s2"&gt;,
    [Parameter(Mandatory)] 
    [string]&lt;/span&gt;&lt;span class="nv"&gt;$StorageAccountResourceGroup&lt;/span&gt;&lt;span class="s2"&gt;
  )

  &lt;/span&gt;&lt;span class="nv"&gt;$storageAccountKey&lt;/span&gt;&lt;span class="s2"&gt; = (Get-AzureRmStorageAccountKey -ResourceGroupName
      &lt;/span&gt;&lt;span class="nv"&gt;$StorageAccountResourceGroup&lt;/span&gt;&lt;span class="s2"&gt; -AccountName &lt;/span&gt;&lt;span class="nv"&gt;$StorageAccountName&lt;/span&gt;&lt;span class="s2"&gt;).Value[0]
  return New-AzureStorageContext -StorageAccountName &lt;/span&gt;&lt;span class="nv"&gt;$StorageAccountName&lt;/span&gt;&lt;span class="s2"&gt; 
      -StorageAccountKey &lt;/span&gt;&lt;span class="nv"&gt;$storageAccountKey&lt;/span&gt;&lt;span class="s2"&gt;
}

Export-ModuleMember -Function Get-StorageAccountContext
Export-ModuleMember -Function Backup-StorageAccount
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a script to launch the backup
Backup-Storage-Account.ps1
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$destCtx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Get-StorageAccountContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-StorageAccountName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$destStorageAccountName&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nt"&gt;-StorageAccountResourceGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$destResourceGroup&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;    
    &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccountName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;storageAccountName&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$srcResourceGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccount&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resourceGroup&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$srcCtx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Get-StorageAccountContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-StorageAccountName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcStorageAccountName&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nt"&gt;-StorageAccountResourceGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcResourceGroup&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;Backup-StorageAccount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SrcCtx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$srcCtx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-DestCtx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$destCtx&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a task group in Azure DevOps&lt;/li&gt;
&lt;li&gt;Add the &lt;code&gt;Azure PowerShell&lt;/code&gt; task, so the script will run in an Azure context and will be authenticated to the Storage Accounts you want to backup (make sure that Azure DevOps has access to your Azure Subscription)&lt;/li&gt;
&lt;li&gt;Here's the YAML of that task. 
&amp;gt; Note that I used variables to make it more reusable in different environments&lt;/li&gt;
&lt;li&gt;$(subscription) -&amp;gt; So you can target different Azure subscriptions&lt;/li&gt;
&lt;li&gt;$(RepositoryPath) -&amp;gt; Git repository path that contains the scripts&lt;/li&gt;
&lt;li&gt;$(EnvironmentCode) -&amp;gt; Variable that can be used in your PowerShell script to make custom logic depending on the environment
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AzurePowerShell@3&lt;/span&gt;
  &lt;span class="na"&gt;displayName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Backup&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PowerShell&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Script'&lt;/span&gt;
  &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;azureSubscription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(subscription)'&lt;/span&gt;
    &lt;span class="na"&gt;ScriptPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$(RepositoryPath)\src\Backup\Scripts\Backup-Storage-Accounts.ps1'&lt;/span&gt;
    &lt;span class="na"&gt;ScriptArguments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-EnvironmentCode&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$(EnvironmentCode)'&lt;/span&gt;
    &lt;span class="na"&gt;FailOnStandardError&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;azurePowerShellVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LatestVersion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a new Release build pipeline with all your environments as stages&lt;/li&gt;
&lt;li&gt;Add an artifact and select &lt;code&gt;Azure Repos&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_HOylJZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/2019-05-22-09_51_44-Perform-Storage-Account-Backup---Pipelines.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_HOylJZv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/2019-05-22-09_51_44-Perform-Storage-Account-Backup---Pipelines.png" alt="Add artifact to Azure repos" title="Add artifact to Azure repos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set a schedule to kick off the backups on all environments&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QEE1Y94E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/2019-05-22-09_15_02-Perform-Storage-Account-Backup---Pipelines.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QEE1Y94E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/2019-05-22-09_15_02-Perform-Storage-Account-Backup---Pipelines.png" alt="Configure pipeline" title="Configure pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure each environment to use your Task Group&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NynKHOZh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/Env-tasks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NynKHOZh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/Env-tasks.png" alt="Environment Task" title="Environment Task"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure your variables for each environment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--87QjOl8R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/variables.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--87QjOl8R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/variables.png" alt="Variables" title="Variables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can now look at all the backup runs and get notifications for free when it fails (default behavior of Azure DevOps when a build fails)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aAB68a-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/backup-runs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aAB68a-z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2019/05/backup-runs.png" alt="Backup runs" title="Backup runs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to set up for multiple environments with the release pipeline&lt;/li&gt;
&lt;li&gt;Audit trail of all the changes in the release pipeline&lt;/li&gt;
&lt;li&gt;Support for various environments&lt;/li&gt;
&lt;li&gt;Overview of all the backup runs&lt;/li&gt;
&lt;li&gt;Built-in notifications on failure&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You need an Azure DevOps account (but you can subscribe to a free plan here)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes the solution is more straightforward than it looks. You need to leverage existing tools that you know. Try to think outside the box, and you'll find out that your absurd ideas might not be that crazy after all. An essential skill for a developer is the ability to solve business problems in new creative ways using technology.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>dotnet</category>
      <category>backup</category>
      <category>storage</category>
    </item>
    <item>
      <title>How many unit tests are good enough | Property-Based testing</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Mon, 13 Apr 2020 14:35:52 +0000</pubDate>
      <link>https://forem.com/mbernard/how-many-unit-tests-are-good-enough-property-based-testing-5gi5</link>
      <guid>https://forem.com/mbernard/how-many-unit-tests-are-good-enough-property-based-testing-5gi5</guid>
      <description>&lt;p&gt;As I was mentioning in my &lt;a href="https://blog.miguelbernard.com/whats-wrong-with-the-current-state-of-unit-testing/"&gt;previous post&lt;/a&gt;, the way we are doing unit testing today has many issues. One of the biggest problems is to know for sure when we have enough tests to be confident to release in production. Why is that? Well, we mostly base our tests on examples, so it's tough to know for sure if we covered all the edge cases and that we have all the required samples.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tale of a developer
&lt;/h1&gt;

&lt;p&gt;Let's use a story to demonstrate what I mean.&lt;/p&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here, the gray circle will be defining what the client wants, the &lt;code&gt;X&lt;/code&gt;s will visually represent the tests, and the red lines will represent the actual output of the algorithm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Once upon a time
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: Could you create an algorithm that draws a circle given a radius? Something like that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--syMM-_bS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/CircleReq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--syMM-_bS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/CircleReq.jpg" alt="CircleReq"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: Of course! Easy peasy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  After some time
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: Alright I'm done, it's working.&lt;br&gt;
&lt;strong&gt;Client&lt;/strong&gt;: How do you know if it's working properly? Did you test it?&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: Well... I made it run on my machine. If you want, I can add a unit test to prove it.&lt;br&gt;
&lt;strong&gt;Client&lt;/strong&gt;: That would be great.&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: Here you go. I added a unit test that makes sure that the point (1,0) is part of the circle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2NF7kHVr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_1_0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2NF7kHVr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_1_0.jpg" alt="Circle_1_0"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: How do you know that you are not only drawing a horizontal line that passes through that point?&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: Ok, here's another test that makes sure that the point (0,1) is part of the circle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2t-jeBDL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_0_1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2t-jeBDL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_0_1.jpg" alt="Circle_0_1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: What about coordinates that are not &lt;code&gt;int&lt;/code&gt;?&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: Sure. I added another test for this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MuaY8H0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_05_05.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MuaY8H0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_05_05.jpg" alt="Circle_05_05"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: I don't want just a quarter of a circle. Can you make sure other quadrants are also supported?&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: Arrrrg... Sure. I added another test for this. I'm pretty sure we covered everything. We should ship it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c_pbFK54--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_-078_023.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c_pbFK54--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_-078_023.jpg" alt="Circle_-078_023"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: Alright, after all, you are the expert. Let's ship it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Once in production
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vHPU7DRi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle-in-prod.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vHPU7DRi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle-in-prod.jpg" alt="Circle-in-prod"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Client&lt;/strong&gt;: What the heck. It looks nothing like the circle I wanted.&lt;br&gt;
&lt;strong&gt;Developer&lt;/strong&gt;: I don't understand. All my tests are passing, which means this should work just fine according to your requirements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AnUj4dCi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_prod_tests.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AnUj4dCi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/04/Circle_prod_tests.jpg" alt="Circle_prod_tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer&lt;/strong&gt;: Maybe if I add another test, I'll find the issue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The truth is
&lt;/h2&gt;

&lt;p&gt;In fact, with this kind of problem, you'll never be done adding examples. It's because a circle is composed of an infinity of points, which makes it almost impossible to validate with example-based tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do we do then
&lt;/h2&gt;

&lt;p&gt;At this point, I'm pretty sure we all agree that we need a better strategy to test this. That's precisely the kind of problem where &lt;a href="https://blog.miguelbernard.com/whats-wrong-with-the-current-state-of-unit-testing/"&gt;Property-Based testing&lt;/a&gt; shines. Instead of validating points along the circle, let's try to understand and model the relationship between the input (the radius) and the output (the circle). It turns out that this relationship is well known and defined in the math world.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A circle can be defined as the locus of all points that satisfy the equation&lt;br&gt;
x^2 + y^2 = r^2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's an excellent property for a test. With only one test, we can validate any point of a circle given a radius. Voilà!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Stay tuned for my next blog post, where we'll solve a real problem with C# and property-based testing.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>propertybasedtest</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>What's wrong with the current state of unit testing</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 05 Apr 2020 18:03:59 +0000</pubDate>
      <link>https://forem.com/mbernard/what-s-wrong-with-the-current-state-of-unit-testing-18gk</link>
      <guid>https://forem.com/mbernard/what-s-wrong-with-the-current-state-of-unit-testing-18gk</guid>
      <description>&lt;p&gt;Unit testing nowadays is pretty much always done using a technique called example-based testing. The method is simple; we run a series of examples against an algorithm, and we validate that we get the expected result.&lt;/p&gt;

&lt;p&gt;e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Fact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GivenThree_WhenCalculate_ThenFiveIsReturned&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Given&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// When&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Then&lt;/span&gt;
    &lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This technique is relatively easy to understand and implement. However, it's far from being all rainbows and unicorns. In this article, we'll go over property-based testing, an alternative approach that shines where example-based testing tends to fall short.&lt;/p&gt;

&lt;p&gt;The main problems with those tests are that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They don't scale&lt;/li&gt;
&lt;li&gt;They don't help you find edge cases&lt;/li&gt;
&lt;li&gt;They are brittle&lt;/li&gt;
&lt;li&gt;They don't explain the requirement&lt;/li&gt;
&lt;li&gt;They tend to be too specific to the implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  We all do this
&lt;/h2&gt;

&lt;p&gt;If you are like most of us, mortals, you are probably terrible at using TDD, which means that in the best-case scenario, you add your tests after coding the actual method. Moreover, I bet that you write an empty test shell calling your method under test, take the output, and then write your assertion with that value. Let's be honest. The temptation to reach a better code coverage is just too strong that we have all done it at some point. Then, if you have a bug in your code, you effectively only coded a buggy test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Property-based testing
&lt;/h2&gt;

&lt;p&gt;Property-based testing is an alternative approach that can deal with all the shortcomings of example-based tests. However, it's by no means a full replacement, as example-based tests are still excellent in many cases. The best approach is to have the right mix of the two in your test suite.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's a property
&lt;/h3&gt;

&lt;p&gt;When we are talking about properties here, we don't mean properties of C# classes. We use the term property here in a more abstract way. Think of it as a characteristic, trait, attribute, feature, or quality of an algorithm.&lt;/p&gt;

&lt;p&gt;Simple definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A property is a condition that will always be true for a set of valid inputs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Testing method
&lt;/h3&gt;

&lt;p&gt;The first thing to do when you want to create a property-based test is to understand and represent the relationship between inputs and outputs. Then, use randomly generated inputs to express deterministic expected results. &lt;/p&gt;

&lt;p&gt;Said like that, it seems complex, but you'll see, it's more straightforward than it sounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Let's try the technique with a simple example; the &lt;code&gt;Add&lt;/code&gt; method. The signature looks like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you try to test this method with examples, you'll never be done for sure, as there's an infinite combination of numbers that you can add together. So how can we be sure that our &lt;code&gt;Add&lt;/code&gt; method is behaving correctly in every situation?&lt;/p&gt;

&lt;p&gt;First, try to think of what makes the addition different from the other mathematical operations like subtraction and multiplication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Properties
&lt;/h3&gt;

&lt;p&gt;The first property is called &lt;code&gt;commutativity&lt;/code&gt;. For those of you that don't have a math major, here is a simple definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When I add two numbers, the result should not depend on the order of the parameters.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// False&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This property is true for addition and multiplication, but not for subtraction.  Translated to a test in C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Then&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The second property is called &lt;code&gt;associativity&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When I add two numbers, the order of the operations doesn't matter.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)+&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;+(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)-&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;-(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// False&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)*&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Again, this property is true for addition and multiplication, but not for subtraction. Translated to a test in C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;input3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input3&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Then&lt;/span&gt;
&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The third and last property of the addition that makes it unique is called &lt;code&gt;identity&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Adding zero is the same as doing nothing.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;  &lt;span class="c1"&gt;// True&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c1"&gt;// False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At last! We found something to differentiate the addition and the multiplication. Translated to a test in C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With three simple tests, we've been able to cover an infinite number of examples. With these, it's impossible to write an implementation of the &lt;code&gt;Add&lt;/code&gt; method that doesn't behave properly. That's precisely the way mathematicians define concepts. They describe the properties. If you look up the &lt;a href="https://en.wikipedia.org/wiki/Addition#Properties"&gt;definition&lt;/a&gt; of the addition, you'll find something interesting. It's defined as commutativity, associativity, and identity.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>propertybasedtesting</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>What are default interface methods in C# 8.0?</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 29 Mar 2020 18:45:11 +0000</pubDate>
      <link>https://forem.com/mbernard/what-are-default-interface-methods-in-c-8-0-3jog</link>
      <guid>https://forem.com/mbernard/what-are-default-interface-methods-in-c-8-0-3jog</guid>
      <description>&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Last September, Microsoft released a bunch of new features with C# 8.0. One of the major features that they introduced is Default interface methods. In this post, we'll explain what they are, show a few examples and provide guidance to avoid common pitfalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are default interface methods in C# 8.0
&lt;/h2&gt;

&lt;p&gt;Interfaces in C# used to be definitions or contracts without any behavior. This assumption is no longer true. Now, with default interface methods, you can define a default body for any interface methods. When you do so, they mostly behave like virtual methods in an abstract class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are default interface methods important
&lt;/h2&gt;

&lt;p&gt;If they behave like virtual methods in an abstract class, why not simply use an abstract class? There is one big difference that justifies their existence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In C#, you can only inherit from one base class, but you can implement as many interfaces as you want.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That subtle point makes all the difference when it comes to code reuse, a.k.a. the &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;Don't Repeat Yourself (DRY) principle&lt;/a&gt;. That new feature will enable many scenarios that were previously difficult or impossible to achieve.&lt;/p&gt;

&lt;p&gt;e.g.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-methods-versions#extend-the-default-implementation"&gt;Extend interfaces safely by adding methods with implementations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-methods-versions#provide-parameterization"&gt;Create parameterized implementations to provide greater flexibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Enable implementers to provide a more specific implementation in the form of an override&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real examples of default interface methods
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Without default interface methods
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConsoleLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TraceLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For every implementation of &lt;code&gt;ILogger&lt;/code&gt; we have to repeat this same code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  With default interface methods
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConsoleLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TraceLogger&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;WriteCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogLevel&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Information&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceWarning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;Trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TraceError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Haaaaa... this is much better. Now the implementations only contain the relevant code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pitfall to avoid
&lt;/h2&gt;

&lt;p&gt;As much as multiple inheritance is awesome, you also need to be very mindful of the dreaded &lt;a href="https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem"&gt;diamond problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---hLQl37a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/02/Diamond_inheritance-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---hLQl37a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.miguelbernard.com/content/images/2020/02/Diamond_inheritance-1.png" alt="Diamond_inheritance-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and C have overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C?&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;There, you have another great tool to put in your toolbox to keep your code clean and maintainable. This approach is also very non-intrusive and won't conflict with existing code, which means it will be easy to slowly adopt it. If you want to hear more on this subject, let me know in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8?ranMID=24542&amp;amp;ranEAID=je6NUbpObpQ&amp;amp;ranSiteID=je6NUbpObpQ-EyoMi4FWnp4hokdeBjiwDw&amp;amp;epi=je6NUbpObpQ-EyoMi4FWnp4hokdeBjiwDw&amp;amp;irgwc=1&amp;amp;OCID=AID2000142_aff_7593_1243925&amp;amp;tduid=(ir__ud6j69e26wkftihokk0sohzg232xlifmpiyvvasm00)(7593)(1243925)(je6NUbpObpQ-EyoMi4FWnp4hokdeBjiwDw)()&amp;amp;irclickid=_ud6j69e26wkftihokk0sohzg232xlifmpiyvvasm00#default-interface-methods"&gt;Microsoft documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/default-interface-methods-versions"&gt;Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem"&gt;diamond problem&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>aspnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>C# 8.0 Indices and ranges</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 22 Mar 2020 01:02:58 +0000</pubDate>
      <link>https://forem.com/mbernard/c-8-0-indices-and-ranges-16im</link>
      <guid>https://forem.com/mbernard/c-8-0-indices-and-ranges-16im</guid>
      <description>&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compared to other languages, C# was way behind in capabilities to handle data efficiently. Well, those days are over now. Microsoft just improved the C# syntax, making it easier for developers to manage data in arrays.&lt;/p&gt;

&lt;h1&gt;
  
  
  Manipulating Arrays
&lt;/h1&gt;

&lt;p&gt;Have you ever had to manipulate a large set of data in multiple arrays? Of course, you have! And I guess your experience wasn't that good. Compared to other languages, C# was way behind in capabilities to handle data efficiently. Well, those days are over now. Microsoft just improved the C# syntax, making it easier for developers to manage data in arrays.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new guys
&lt;/h2&gt;

&lt;p&gt;Two new operators have been introduced in C# 8.0 to give you all the power you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The 'index from the end' operator: &lt;code&gt;^&lt;/code&gt;, which specifies that an index is relative to the end of the sequence; and&lt;/li&gt;
&lt;li&gt;The 'range' operator: &lt;code&gt;..&lt;/code&gt;, which specifies the start and end of a range.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important notes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;^0&lt;/code&gt; index is the same as &lt;code&gt;sequence[sequence.Length]&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;Be careful, &lt;code&gt;sequence[^0]&lt;/code&gt; &lt;strong&gt;does&lt;/strong&gt; throw an &lt;code&gt;IndexOutOfRangeException&lt;/code&gt;, just as &lt;code&gt;sequence[sequence.Length]&lt;/code&gt; does.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;For any number &lt;strong&gt;n&lt;/strong&gt;, the index &lt;code&gt;^n&lt;/code&gt; is the same as &lt;code&gt;sequence.Length - n&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For ranges, the start of the range is &lt;strong&gt;inclusive&lt;/strong&gt;, but the end of the range is &lt;strong&gt;exclusive&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The range &lt;code&gt;[0..0^]&lt;/code&gt; represents the entire sequence, just as &lt;code&gt;[0..sequence.Length]&lt;/code&gt; or &lt;code&gt;[..]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A range doesn't need to be completely defined, e.g.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[..3]&lt;/code&gt; -&amp;gt; give me everything from the start of the array to index &lt;code&gt;3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[2..]&lt;/code&gt; -&amp;gt; give me everything from index &lt;code&gt;2&lt;/code&gt; until the end of the array.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[..]&lt;/code&gt; -&amp;gt; give me everything&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Confused? I promise it will all make sense after this. Let's look at a few examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt;                &lt;/span&gt;&lt;span class="c1"&gt;// index from start    index from end&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"The"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// 0                   ^9&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"quick"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// 1                   ^8&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"brown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="c1"&gt;// 2                   ^7&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"fox"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// 3                   ^6&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"jumped"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;   &lt;/span&gt;&lt;span class="c1"&gt;// 4                   ^5&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"over"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// 5                   ^4&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"the"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="c1"&gt;// 6                   ^3&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;     &lt;/span&gt;&lt;span class="c1"&gt;// 7                   ^2&lt;/span&gt;
&lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="s"&gt;"dog"&lt;/span&gt;&lt;span class="err"&gt;       &lt;/span&gt;&lt;span class="c1"&gt;// 8                   ^1&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;As you can see here &lt;code&gt;words[^0]&lt;/code&gt; is equal to &lt;code&gt;words[9]&lt;/code&gt;, which is out of range&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Give me some more
&lt;/h3&gt;

&lt;p&gt;Alright, alright. Here are some more ways to use it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;allWords&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[..];&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// contains "The" through "dog".&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;firstPhrase&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[..&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// contains "The" through "fox".&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;lastPhrase&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;6.&lt;/span&gt;&lt;span class="p"&gt;.];&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// contains "the, "lazy" and "dog".&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;lazyDog&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;2.&lt;/span&gt;&lt;span class="p"&gt;.^&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// contains "lazy" and "dog".&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Index&lt;/code&gt; and &lt;code&gt;Range&lt;/code&gt; are also .NET types, which means you can create variables of those types, name them for code clarity, and reuse them over and over.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;^&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;Range&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="m"&gt;1.&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This is super powerful, I can't wait to use it in my projects. This will help so much with reducing noise when using index calculations as well as making the code more maintainable. Thank you Microsoft for this great addition to the language ❤️.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8"&gt;https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>aspnet</category>
      <category>dotnetcore</category>
    </item>
    <item>
      <title>Asynchronous streams in C# 8.0</title>
      <dc:creator>Miguel Bernard</dc:creator>
      <pubDate>Sun, 15 Mar 2020 21:56:43 +0000</pubDate>
      <link>https://forem.com/mbernard/asynchronous-streams-in-c-8-0-33la</link>
      <guid>https://forem.com/mbernard/asynchronous-streams-in-c-8-0-33la</guid>
      <description>&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Asynchronous streams: what are they?
&lt;/h1&gt;

&lt;p&gt;Asynchronous streams are a new way to iterate over a stream of data. It was previously possible to do this synchronously in C#. Now you can do it even if the stream producer is asynchronous! Woot, woot!&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need to get started
&lt;/h2&gt;

&lt;p&gt;To enable asynchronous streams you need 3 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your method must be &lt;code&gt;async&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The return type of your method must be &lt;code&gt;IAsyncEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The method body must contain at least one &lt;code&gt;yield return&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How is this useful?
&lt;/h2&gt;

&lt;p&gt;To show the value of this feature, nothing is better than a real use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use case
&lt;/h3&gt;

&lt;p&gt;As a user, I want to count all the users' names that contain the letter 'n'.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;All the users' names are in an SQL database. That database contains millions of users.&lt;/p&gt;

&lt;h3&gt;
  
  
  The problem
&lt;/h3&gt;

&lt;p&gt;The problem is that this dataset is really big and to calculate the final value we'll need to load it all. If you try to load that many records in memory, you'll probably run out of memory and get an &lt;code&gt;OutOfMemoryException&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, yes... I know, you can compute this value directly with a SQL query. Remember, this is just a simple example to show how the feature works.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Let's look at how it's done with async streams
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Producer
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;IAsyncEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAllNames&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pageIndex&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;hasMore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// **** IMPORTANT ****&lt;/span&gt;
        &lt;span class="c1"&gt;// Never EVER do this in a real application. The following code block is&lt;/span&gt;
        &lt;span class="c1"&gt;// not secure and could be subject to an attack known as SQL Injection.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SqlConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ConnectionString here"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SqlCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="s"&gt;$"
&lt;/span&gt;            &lt;span class="n"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
            &lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Users&lt;/span&gt;
            &lt;span class="n"&gt;ORDER&lt;/span&gt; &lt;span class="n"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
            &lt;span class="n"&gt;OFFSET&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pageIndex&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;ROWS&lt;/span&gt;
            &lt;span class="n"&gt;FETCH&lt;/span&gt; &lt;span class="n"&gt;NEXT&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;ROWS&lt;/span&gt; &lt;span class="n"&gt;ONLY&lt;/span&gt;&lt;span class="s"&gt;",
&lt;/span&gt;            &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteReaderAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// This is the "Name" column&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;pageIndex&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
        &lt;span class="n"&gt;hasMore&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasRows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasMore&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Consumer
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CountNamesWithN&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;namesContainingN&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;GetAllNames&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;namesContainingN&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;namesContainingN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is fairly straightforward. From the producer's side, simply use&lt;br&gt;
&lt;code&gt;yield return&lt;/code&gt; to stream some data on demand. On the consumer's side, notice the use of &lt;code&gt;await&lt;/code&gt; right before the &lt;code&gt;foreach&lt;/code&gt; keyword, this is where the magic happens. The rest behaves just like a plain old &lt;code&gt;foreach&lt;/code&gt; over a synchronous&lt;br&gt;
&lt;code&gt;IEnumerable&lt;/code&gt;, but now it's asynchronous.&lt;/p&gt;

&lt;p&gt;At first, this may look like magic, but under the hood, while iterating over the stream of data on the consumer's side, new database queries are issued seamlessly  when it needs to load more data. This allows us to nicely stream our data without blowing up the memory, and all the complexity is managed by&lt;br&gt;
&lt;code&gt;IAsyncEnumerable&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; that are now part of our daily development tools, this new feature will simplify a lot of code that you had to do manually. Let me know in the comments how you think this could help you in your day to day work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Also in this &lt;a href="https://blog.miguelbernard.com/csharp-8-0-new-features/"&gt;series&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-nullable-reference-types-are-here/"&gt;C# 8.0 Nullable Reference types are here!&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/pattern-matching-in-csharp/"&gt;Pattern matching in C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/asynchronous-streams/"&gt;Asynchronous streams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/c-8-0-indices-and-ranges"&gt;Indices and ranges&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/what-are-default-interface-methods-in-c-8-0"&gt;Default interface methods&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.miguelbernard.com/5-tips-to-improve-your-productivity-in-c-8-0"&gt;5 tips to improve your productivity in C# 8.0&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;All code samples are available on &lt;a href="https://github.com/mbernard/csharp8sample"&gt;github&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>asp</category>
    </item>
  </channel>
</rss>
