<?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>DEV Community: Jan Doubek</title>
    <description>The latest articles on DEV Community by Jan Doubek (@jdoubek).</description>
    <link>https://dev.to/jdoubek</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%2F485947%2F8a80fd21-589f-4698-b68f-e579488ed269.jpg</url>
      <title>DEV Community: Jan Doubek</title>
      <link>https://dev.to/jdoubek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jdoubek"/>
    <language>en</language>
    <item>
      <title>Inspiration is Everywhere: 5 Diverse Sources to Tap Into</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 06 Jun 2023 15:20:35 +0000</pubDate>
      <link>https://dev.to/jdoubek/inspiration-is-everywhere-5-diverse-sources-to-tap-into-3f80</link>
      <guid>https://dev.to/jdoubek/inspiration-is-everywhere-5-diverse-sources-to-tap-into-3f80</guid>
      <description>&lt;p&gt;One key reason I find myself drawn to social media is its power to inspire through the diverse perspectives of people.&lt;/p&gt;

&lt;p&gt;People tweeting or blogging about stuff they do or like, youtube videos and podcasts on different topics, all of these embed little hints, which may trigger some form of positive response in your brain, causing it to reshape your perspective or spur you into action.&lt;/p&gt;

&lt;p&gt;My aim with this post is to unveil my top five sources of inspiration. Perhaps they'll spark a little inspiration for you too, or who knows, they could even potentially change the course of your life. :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration #1 - Lex Fridman Podcast
&lt;/h2&gt;

&lt;p&gt;The diversity of guests on this podcast and also the depth to which some of the topics are discussed are what make this podcast truly inspiring. Each podcast provides profound insights which always teach me something new - both professionally (when the podcasts are technically oriented, such as discussing programming languages or AI) and personally (when guests are experts in relationships, parenting, etc.).&lt;/p&gt;

&lt;p&gt;Find Lex's podcast on YouTube here: &lt;a href="https://www.youtube.com/@lexfridman"&gt;https://www.youtube.com/@lexfridman&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration #2 - Scott Hanselman's Tweets
&lt;/h2&gt;

&lt;p&gt;Among the many tech influencers these days, Scott Hanselman stands out as particularly engaging. He's an expert in a wide range of technical subjects, from software development and system architecture to productivity hacks and career advice.&lt;/p&gt;

&lt;p&gt;What I appreciate the most about following him though is his ability to keep up to date with developments in both the technical and non-technical realms, and his eagerness to share these insights with his followers.&lt;/p&gt;

&lt;p&gt;Follow Scott at &lt;a href="https://twitter.com/shanselman"&gt;https://twitter.com/shanselman&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration #3 - Travis Eliot's Life Wisdom
&lt;/h2&gt;

&lt;p&gt;Travis isn't just an excellent yoga instructor (you can get a taste of his yoga classes on his &lt;a href="https://www.youtube.com/@traviseliotyoga"&gt;YouTube channel&lt;/a&gt; or his online yoga studio, &lt;a href="https://www.innerdimensiontv.com/"&gt;Inner Dimension&lt;/a&gt;), but he also generates content around healthy living, mindfulness, and life wisdom. His podcast series, The Be Ultimate Podcast, features over 80 episodes packed with knowledge and tips for healthier living. I wholeheartedly recommend his content to anyone in the tech industry, as yoga, meditation and mindfulness are the perfect antidotes to the materialistically-focused world of tech.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/@traviseliotyoga"&gt;https://www.youtube.com/@traviseliotyoga&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.innerdimensiontv.com/"&gt;https://www.innerdimensiontv.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration #4 - John Green's Books
&lt;/h2&gt;

&lt;p&gt;John is an excellent writer and his books are always unconventional and entertaining. But they offer more than just leisure; through John's deep understanding of the teenage experience, I also gain invaluable insights into the world that my children navigate every day.&lt;/p&gt;

&lt;p&gt;You can discover John Green's collection of books on platforms like &lt;a href="https://www.goodreads.com/author/show/1406384.John_Green"&gt;Goodreads&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration #5 - Hashnode Blogs
&lt;/h2&gt;

&lt;p&gt;Last, but certainly not least, my recently discovered passion - blogging.&lt;/p&gt;

&lt;p&gt;Producing content and sharing thoughts through blogging in general is something I truly enjoy, though it can sometimes be a challenging task. Hence, I need both inspiration and a seamless and hassle-free blogging process.&lt;/p&gt;

&lt;p&gt;That's exactly where Hashnode shines. It enables me to produce content without getting bogged down by worries about hosting, backups or struggling with the syntax of markup languages.&lt;/p&gt;

&lt;p&gt;What's more, Hashnode has an incredible community of professionals who produce content regularly. This community provides a large initial audience for my writing. But perhaps even more important, I can always find new inspiration and motivation by reading what other Hashnode bloggers write about.&lt;/p&gt;

&lt;p&gt;If you haven't already, go ahead and give Hashnode a try at &lt;a href="https://hashnode.com/"&gt;https://hashnode.com/&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Journey Continues...
&lt;/h2&gt;

&lt;p&gt;Did you find inspiration in any of these resources? Great! Please share your thoughts in the comments below.&lt;/p&gt;

&lt;p&gt;If however none of these resonated with you, I would recommend that you at least take a look through some of my previous posts on the &lt;a href="https://mydevtricks.com/"&gt;My Dev Tricks website&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>learning</category>
    </item>
    <item>
      <title>Python Made Easy: Your Step-by-Step Journey with ChatGPT</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 28 Feb 2023 14:12:05 +0000</pubDate>
      <link>https://dev.to/jdoubek/python-made-easy-your-step-by-step-journey-with-chatgpt-m31</link>
      <guid>https://dev.to/jdoubek/python-made-easy-your-step-by-step-journey-with-chatgpt-m31</guid>
      <description>&lt;p&gt;Whether you're a seasoned Microsoft tech stack developer or just starting out, this tutorial is the ideal place to begin your Python journey. And, to sweeten things up a little bit, you're going to use &lt;a href="https://chat.openai.com/"&gt;&lt;strong&gt;ChatGPT&lt;/strong&gt;&lt;/a&gt; to help you get started!&lt;/p&gt;

&lt;p&gt;Without further ado, let's dive into the tutorial and start learning Python!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #1 - Install Python
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, download the latest version of Python for Windows from the &lt;a href="https://www.python.org/downloads/"&gt;Python Downloads page&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute the downloaded installer package.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the Python installer UI, take the quick path by clicking on the &lt;strong&gt;Install now&lt;/strong&gt; button. Be sure to check the "Add python.exe to PATH" option, as this will at a later point make it possible to execute python and pip from the command line.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3zoVxesL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgoqk8mbtalixnksbk8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3zoVxesL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fgoqk8mbtalixnksbk8d.png" alt="python installer" width="465" height="80"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once installed, proceed to the next step to get the development environment ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #2 - Install Visual Studio Code
&lt;/h2&gt;

&lt;p&gt;We'll be using &lt;a href="https://code.visualstudio.com/"&gt;Visual Studio Code&lt;/a&gt; as our Python programming playground. VS Code is my go-to development environment for open-source development languages. Read more about it in my previous blog post &lt;a href="https://mydevtricks.com/visual-studio-code-features-1"&gt;5 Awesome Visual Studio Code Features&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Download VS Code from &lt;a href="https://code.visualstudio.com/download"&gt;code.visualstudio.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the installer, accepting default installation options.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the installation finishes, open Visual Studio Code to set up the necessary extensions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #3 - Install Python Extensions
&lt;/h2&gt;

&lt;p&gt;If you're new to Visual Studio Code, I recommend going through some basic usage tutorials first. The &lt;a href="https://code.visualstudio.com/docs"&gt;Getting Started&lt;/a&gt; section of the official VS Code documentation seems like a great place to start learning.&lt;/p&gt;

&lt;p&gt;To get syntax highlighting, IntelliSense and debugging support for Python scripts, we'll need to install some Visual Studio Code extensions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Open the Extensions panel&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search for "python"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The first extension found should be &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python"&gt;Python&lt;/a&gt; (by Microsoft).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SEcuPPTb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgugjfilnzc8kn6dmy5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SEcuPPTb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgugjfilnzc8kn6dmy5o.png" alt="python extension" width="308" height="151"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt; to install the extension.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You're now set up to start writing your first python script!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #4 - Our Very First Python Script
&lt;/h2&gt;

&lt;p&gt;Before we delve into writing Python code, let's create a very basic "project" for the code files. In Visual Studio Code, the easiest way how to do this is to open a folder on your local drive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In VS Code, go &lt;strong&gt;File-&amp;gt;Open Folder&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open a folder on your drive, for example, &lt;code&gt;C:\Dev\PythonTest&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When prompted, click "Yes, I trust the authors".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In the File Explorer panel, click on the &lt;strong&gt;New File&lt;/strong&gt; icon and specify &lt;code&gt;test1.py&lt;/code&gt; as the name of the new python file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P_D0Kem6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fctcr5ekjyyad2gx3qaf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P_D0Kem6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fctcr5ekjyyad2gx3qaf.png" alt="new file" width="353" height="91"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add the following content to the file and save:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;We're now ready to run and debug our python script for the first time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #5 - Debug and Run
&lt;/h2&gt;

&lt;p&gt;As with most programming languages, there are two basic ways how to execute scripts written in Python: &lt;strong&gt;Debug&lt;/strong&gt; and &lt;strong&gt;Run&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;Debug&lt;/strong&gt; the Python script in Visual Studio Code, go &lt;strong&gt;Run-&amp;gt;Start Debugging&lt;/strong&gt;, or press &lt;strong&gt;F5&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The first time you do this, you will be asked to select a debug configuration. Pick the "Debug File - Debug the currently active Python file" configuration. This option is sufficient for our simple tests. For more complex debugging scenarios, check out the &lt;a href="https://code.visualstudio.com/docs/python/debugging"&gt;Python debugging in VS Code&lt;/a&gt; documentation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4Fc3AThm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0x3hek6swp8xzbr68iey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4Fc3AThm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0x3hek6swp8xzbr68iey.png" alt="python debug configuration" width="398" height="94"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To &lt;strong&gt;Run&lt;/strong&gt; the Python script in Visual Studio Code, go &lt;strong&gt;Run-&amp;gt;Run Without Debugging&lt;/strong&gt;, or press &lt;strong&gt;Ctrl+F5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In both cases, you should get the following Output written into the VS Code Terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Hello!
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voila, you just executed your very first Python script!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step #6 - Get Your Code on with ChatGPT Code Snippets
&lt;/h2&gt;

&lt;p&gt;Being inspired by a recent post of a fellow blogger &lt;a href="https://blog.jenscaasen.cloud/"&gt;Jens Caasen&lt;/a&gt; and his article &lt;a href="https://blog.jenscaasen.cloud/12-ways-to-make-chatgpt-your-personal-junior-developer-with-examples"&gt;12 ways to make ChatGPT your personal Junior Developer (with examples)&lt;/a&gt;, I've decided to ask &lt;strong&gt;ChatGPT&lt;/strong&gt; to help us come up with some fun introductory Python code snippets.&lt;/p&gt;

&lt;p&gt;Utilizing ChatGPT to get you started with Python is a great choice for (at least) two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You can quickly get sample code for topics that interest you, for example: For loops, JSON, Rest API, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You get to sharpen your ChatGPT usage skills. ChatGPT and AI in general are the future and the faster we adopt (and accept) it, the bigger competitive advantage we'll get!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Snippet #1: 99 Bottles of Beer on the Wall
&lt;/h3&gt;

&lt;p&gt;For starters, we're going to ask for some very basic Python sample code:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me:&lt;/em&gt; what would be a useful but fun snippet of Python code for someone who's very new to the Python language?&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bottles of beer on the wall, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bottles of beer."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"Take one down, pass it around, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; bottles of beer on the wall."&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;&lt;em&gt;ChatGPT:&lt;/em&gt; This code snippet uses a &lt;strong&gt;for loop&lt;/strong&gt; and the &lt;strong&gt;range()&lt;/strong&gt; function to count down from 99 to 1, and the &lt;strong&gt;print()&lt;/strong&gt; function to print the lyrics of the song. It also makes use of &lt;strong&gt;string interpolation&lt;/strong&gt; (f"{...}") to insert dynamic values into the string being printed. This code snippet is a simple example of how you can use Python to automate repetitive tasks and generate fun output!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;(emphasis mine)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Snippet #2: How Tall Are You?
&lt;/h3&gt;

&lt;p&gt;This time we ask for a sample illustrating a specific language construct:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me:&lt;/em&gt; something illustrating the if/else condition?&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enter your height in meters: "&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You are tall!"&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="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"You are not tall."&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;&lt;em&gt;ChatGPT:&lt;/em&gt; This code snippet uses an if statement and an else clause to determine if a person's height is greater than or equal to 1.8 meters. If the height is greater than or equal to 1.8, the code will print "You are tall!"; otherwise, it will print "You are not tall.". This simple code snippet demonstrates how you can use the if statement and the else clause in Python to make decisions based on conditions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Snippet #3: List of European countries using REST and JSON
&lt;/h3&gt;

&lt;p&gt;Now let's try something a little more complex:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me:&lt;/em&gt; How about an example importing a library, reading a publicly available json file containing world countries and then listing all European countries?&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://restcountries.com/v3.1/all"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;countries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;european_countries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s"&gt;"common"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;countries&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Europe"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"European Countries:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;european_countries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&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;country&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;&lt;em&gt;ChatGPT:&lt;/em&gt; This code snippet first imports the requests library, which allows you to send HTTP requests, and the json library, which provides functions for encoding and decoding JSON data. It then uses the requests.get() function to send a GET request to the endpoint "&lt;a href="https://restcountries.com/v3.1/all"&gt;https://restcountries.com/v3.1/all&lt;/a&gt;" to retrieve information about all countries in the world. The json.loads() function is then used to parse the JSON data returned in the response.&lt;/p&gt;

&lt;p&gt;Next, the code uses a list comprehension to create a list of common names of countries located in the region "Europe". Finally, the code uses a for loop and the print() function to print the names of all European countries.&lt;/p&gt;

&lt;p&gt;This code snippet demonstrates how you can use the requests and json libraries to retrieve information from a publicly available API and process the data in Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good. However, with the default setup of Python and Visual Studio Code that we've established, this example does not work:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sgYQopeH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3t7vew6rqbzh7xeeuhj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sgYQopeH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3t7vew6rqbzh7xeeuhj.png" alt="python import failure" width="403" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's ask ChatGPT to fix it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me:&lt;/em&gt; I'm getting an error saying: Import "requests" could not be resolved&lt;/p&gt;

&lt;p&gt;&lt;em&gt;ChatGPT:&lt;/em&gt; It seems like you don't have the requests library installed in your Python environment. You can install it using the following command:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;pip install requests
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Make sure you have the pip package manager installed, and run the command in your terminal or command prompt. After the installation is complete, you should be able to import the requests library in your Python code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And indeed, as suggested, once we install the &lt;strong&gt;requests&lt;/strong&gt; library using the pip package manager, the code works and outputs a list of European countries.&lt;/p&gt;

&lt;p&gt;Great job, ChatGPT! 👏👏&lt;/p&gt;

&lt;h2&gt;
  
  
  That's a Wrap
&lt;/h2&gt;

&lt;p&gt;I could be going on with the examples for hours, most likely learning something new with every new code snippet generated by ChatGPT.&lt;/p&gt;

&lt;p&gt;However, let's leave some room for your own experimenting.&lt;/p&gt;

&lt;p&gt;And don't forget to share any fun or interesting content that you and ChatGPT come up with in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Is PostgreSQL a worthy alternative to Microsoft SQL Server?</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 07 Feb 2023 13:00:00 +0000</pubDate>
      <link>https://dev.to/jdoubek/is-postgresql-a-worthy-alternative-to-microsoft-sql-server-1p02</link>
      <guid>https://dev.to/jdoubek/is-postgresql-a-worthy-alternative-to-microsoft-sql-server-1p02</guid>
      <description>&lt;p&gt;In line with the title of this blog, I'd like to start posting articles about languages, tools and technologies that I got a chance to use recently.&lt;/p&gt;

&lt;p&gt;One of the technologies that I was lucky to learn is &lt;strong&gt;PostgreSQL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I have always been an avid Microsoft technology stack advocate, so naturally most of the time my RDBMS system of choice was &lt;a href="https://learn.microsoft.com/en-us/sql/sql-server/" rel="noopener noreferrer"&gt;Microsoft SQL Server&lt;/a&gt;. Now, I'm still holding my opinion that Microsoft SQL Server is a great product, which scales wonderfully from small web applications to large enterprise solutions. The fact however is that for any non-trivial applications, i.e. once the database system requirements outgrow the potential of the free &lt;a href="https://learn.microsoft.com/en-us/sql/sql-server/editions-and-components-of-sql-server-2022?view=sql-server-ver16#sql-server-editions" rel="noopener noreferrer"&gt;SQL Server Express edition&lt;/a&gt;, licensing costs may start to become an issue. And that is (at least for me) exactly the point at which &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt; comes into play.&lt;/p&gt;

&lt;h2&gt;
  
  
  At a glance
&lt;/h2&gt;

&lt;p&gt;PostgreSQL is a powerful, open-source relational database management system. Feature-wise PostgreSQL is comparable to Microsoft SQL Server, at least when it comes to RDBMS features. It scales well for large workloads and at the same time - you guessed it - it remains free.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Favorites
&lt;/h2&gt;

&lt;p&gt;There is a ton of introductory articles about PostgreSQL on the web. Rather than adding another one, let me just highlight some of the features that I like and enjoy about PostgreSQL:&lt;/p&gt;

&lt;h3&gt;
  
  
  PostgreSQL is easy to install
&lt;/h3&gt;

&lt;p&gt;The quick and straightforward installation of PostgreSQL is a big contrast to the bulky and slow Microsoft SQL Server installer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You may start your database adventures within minutes of downloading the software.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The PostgreSQL installation process typically involves downloading the software, running the installer, and specifying a few basic configuration settings. If you also opt to install the &lt;a href="https://www.pgadmin.org/" rel="noopener noreferrer"&gt;pgAdmin GUI tool&lt;/a&gt; (a PostgreSQL counterpart to &lt;a href="https://learn.microsoft.com/en-us/sql/ssms/sql-server-management-studio-ssms" rel="noopener noreferrer"&gt;SQL Server Management Studio&lt;/a&gt;), you may start your database adventures within minutes of downloading the software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Good compatibility with Microsoft SQL Server
&lt;/h3&gt;

&lt;p&gt;I was pleasantly surprised when testing the compatibility between the two systems. I mean, there certainly are areas in which the syntax differs, but overall it's not bad at all.&lt;/p&gt;

&lt;p&gt;And for cases where you're porting existing solutions based on Microsoft SQL Server to PostgreSQL, you can take advantage of 3rd party tools that make it easier to perform an initial migration of your SQL server database schemas into PostgreSQL. After evaluating a few of these tools, my ultimate recommendation goes to &lt;a href="https://www.convert-in.com/mss2pgs.htm" rel="noopener noreferrer"&gt;MSSQL-to-PostgreSQL&lt;/a&gt;. This small and easy-to-use tool is fast and performs most of the type conversions automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query execution speed
&lt;/h3&gt;

&lt;p&gt;Query execution speed constitutes one of the crucial factors of a good database system. In my mind, Microsoft SQL Server has always been a synonym for speed, especially when it comes to large enterprise-grade workloads. And honestly, it might've been concerns about query execution speed, which prevented me from even trying out alternative RDBMS solutions before.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PostgreSQL's Query Optimizer does a very good job of consistently delivering efficient query execution plans, resulting in a solid performance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, with PostgreSQL, I was pleasantly surprised. Query speeds are very good. I don't want to compare SQL Server and PostgreSQL execution speeds here, as I have not done any rigorous speed comparison, but given all the years of working with different versions of SQL Server, I must admit that PostgreSQL's Query Optimizer does a very good job of consistently delivering efficient query execution plans, resulting in a solid performance. I'm yet to test large workloads on PostgreSQL, but so far I'm optimistic that PostgreSQL will be able to handle all possible levels of workloads with ease.&lt;/p&gt;

&lt;p&gt;Check out the following screenshot of the &lt;a href="https://www.pgadmin.org/docs/pgadmin4/latest/query_tool.html#explain-panel" rel="noopener noreferrer"&gt;Explain&lt;/a&gt; feature of pgAdmin. This tool greatly helps with analyzing and troubleshooting PostgreSQL query performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjss31c65q1dzwaqjn7wf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjss31c65q1dzwaqjn7wf.png" alt="pgAdmin Explain" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Entity Framework Core provider
&lt;/h3&gt;

&lt;p&gt;One of my concerns when considering supporting a non-Microsoft RDBMS system was how good and mature the implementation of its Entity Framework Core database provider would be. Entity Framework Core represents an important piece of the Microsoft technology stack puzzle. An incomplete or buggy Entity Framework provider could make supporting the PostgreSQL data storage a nightmare.&lt;/p&gt;

&lt;p&gt;And yet again, I got pleasantly surprised. &lt;a href="https://www.npgsql.org/" rel="noopener noreferrer"&gt;Npgsql&lt;/a&gt; - the recommended ADO.NET and Entity Framework (Core) provider - makes the adoption of PostgreSQL an almost seamless experience. Additionally, the Npgsql provider implements those PostgreSQL language elements, which are not present in the Microsoft SQL Server world. Let me mention here at least support for the ILIKE operator, as well as a &lt;a href="https://www.npgsql.org/efcore/api/Microsoft.EntityFrameworkCore.LTree.html?q=ltree" rel="noopener noreferrer"&gt;range of functions&lt;/a&gt; related to the PostgreSQL's &lt;a href="https://www.postgresql.org/docs/current/ltree.html" rel="noopener noreferrer"&gt;LTree data type&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's a short snippet of code that illustrates how easy it is to start using PostgreSQL in your Entity Framework Core application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TestContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseNpgsql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TestContext"&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;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;From the paragraphs above, one could get the idea that everything is perfect with PostgreSQL and that the language and feature compatibility with Microsoft SQL Server is flawless. Well, no - not exactly. Over time I came across several compatibility and tooling issues (Aargh - those unexpected pgAdmin crashes!). But let me leave those to a future blog post.&lt;/p&gt;

&lt;p&gt;Overall, I find PostgreSQL to be a great (and free!!) alternative to Microsoft SQL Server.&lt;/p&gt;

&lt;p&gt;In the spirit of a book from my favorite author John Green - &lt;a href="https://www.goodreads.com/book/show/55145261-the-anthropocene-reviewed" rel="noopener noreferrer"&gt;The Anthropocene Reviewed&lt;/a&gt; - I'm giving PostgreSQL ⭐⭐⭐⭐ (4) stars!&lt;/p&gt;

</description>
      <category>career</category>
      <category>offers</category>
      <category>hiring</category>
    </item>
    <item>
      <title>ToLookup or not ToLookup, that is the question!</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Sun, 30 May 2021 08:23:00 +0000</pubDate>
      <link>https://dev.to/jdoubek/tolookup-or-not-tolookup-that-is-the-question-idj</link>
      <guid>https://dev.to/jdoubek/tolookup-or-not-tolookup-that-is-the-question-idj</guid>
      <description>&lt;p&gt;Shakespeare will hopefully forgive me for abusing a line from his famous Hamlet. In my post, I won't be covering questions of life and death, but rather something much more prosaic - a lesser-known LINQ materialization method - &lt;code&gt;ToLookup&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We all know the famous LINQ materialization methods trio - &lt;code&gt;ToArray&lt;/code&gt;, &lt;code&gt;ToList&lt;/code&gt;, &lt;code&gt;ToDictionary&lt;/code&gt;. There's another such method, which, similarly to the other ones, can be quite useful. The other method is &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.tolookup?view=net-5.0"&gt;Enumerable.ToLookup()&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here's a description of &lt;code&gt;ToLookup&lt;/code&gt; from the Microsoft Docs page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The ToLookup method returns a Lookup, a one-to-many dictionary that maps keys to collections of values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, so &lt;code&gt;ToLookup&lt;/code&gt; is similar to the &lt;code&gt;ToDictionary&lt;/code&gt; method. There's one subtle, but important difference though. With Dictionary, which is basically a typed hash table, you are allowed to associate only a &lt;strong&gt;single value&lt;/strong&gt; to each key, i.e. there's always a &lt;code&gt;one-to-one&lt;/code&gt; mapping between keys and values. &lt;code&gt;ToLookup&lt;/code&gt; on the other hand lets the user store a &lt;strong&gt;collection of values&lt;/strong&gt; for each key, i.e. effectively creating a &lt;code&gt;one-to-many&lt;/code&gt; mapping.&lt;/p&gt;

&lt;p&gt;That's it for theory. Let's have a look at some examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  ToLookup Examples
&lt;/h3&gt;

&lt;p&gt;In the first example, we'll use &lt;code&gt;ToLookup&lt;/code&gt; to split up a collection of numbers into two collections containing even and odd numbers.&lt;br&gt;
&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;numbers&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="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="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="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Using explicit types instead of 'var' for better explicability&lt;/span&gt;
&lt;span class="n"&gt;ILookup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;bool&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;evenNumbersLookup&lt;/span&gt; &lt;span class="p"&gt;=&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;ToLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&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="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;IEnumerable&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="n"&gt;evenNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;evenNumbersLookup&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="n"&gt;IEnumerable&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="n"&gt;oddNumbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;evenNumbersLookup&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="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;"EVEN: "&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;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evenNumbers&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;"ODD:  "&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;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;oddNumbers&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;EVEN: 2,4,6,8
ODD:  1,3,5,7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; of the lookup table here is a boolean determining whether the number is even or odd. The &lt;code&gt;value&lt;/code&gt; is a collection of integers satisfying the even/odd condition.&lt;/p&gt;

&lt;p&gt;Simple, yet effective.&lt;/p&gt;

&lt;p&gt;The lookup &lt;code&gt;key&lt;/code&gt; does not necessarily have to be a true/false value - it can be of any type. In the following example, we use &lt;code&gt;ToLookup&lt;/code&gt; together with an indexed select to split an input set of numbers into groups of 3 elements. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Check out one of my previous &lt;a href="https://mydevtricks.com/linq-gems-indexed-select"&gt;LINQ Gems articles&lt;/a&gt; for more info about indexed select.)&lt;/em&gt;&lt;br&gt;
&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;numbers&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="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="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="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;ILookup&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;,&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="n"&gt;groupedNumbersLookup&lt;/span&gt; &lt;span class="p"&gt;=&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;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seq&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;val&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&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="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;groupedNumbersLookup&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="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;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;$"GROUP &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="m"&gt;1&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;groupedNumbersLookup&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="n"&gt;i&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;The output will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;GROUP 1: 1,2,3
GROUP 2: 4,5,6
GROUP 3: 7,8,9
GROUP 4: 10,11,12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, naturally, the &lt;code&gt;key&lt;/code&gt; of the lookup table is not restricted to numbers only. Here is a nice example of a lookup table having a &lt;code&gt;string&lt;/code&gt; key:&lt;br&gt;
&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;carsInStock&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;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ford"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10000&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="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ford"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;15000&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="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ford"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20000&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="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;15000&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="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Honda"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;25000&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="n"&gt;Make&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Jeep"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20000&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;carValues&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carsInStock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Make&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&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;fordCarsValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Ford"&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;hondaCarsValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;carValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Honda"&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;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;$"Total value of all Ford cars in stock: $&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fordCarsValue&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;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;$"Total value of all Honda cars in stock: $&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;hondaCarsValue&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gives us the output that we'd expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;Total value of all Ford cars in stock: $&lt;/span&gt;45000
&lt;span class="gp"&gt;Total value of all Honda cars in stock: $&lt;/span&gt;40000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Some Noteworthy Facts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Similarly to all the other &lt;code&gt;ToXXX()&lt;/code&gt; methods, &lt;code&gt;ToLookup&lt;/code&gt; as well uses &lt;strong&gt;immediate execution&lt;/strong&gt; to populate the returned Lookup table. Any changes to the original sequence (after the method has returned) won’t change the elements stored in the lookup.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ILookup&amp;lt;TKey,TElement&amp;gt;&lt;/code&gt; interface returned by the &lt;code&gt;ToLookup&lt;/code&gt; call is &lt;strong&gt;read-only&lt;/strong&gt;. It is therefore not possible to append or otherwise modify the lookup table. This is in contrast with &lt;code&gt;IDictionary&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt; returned by &lt;code&gt;ToDictionary&lt;/code&gt;, which constitutes a fully mutable collection of key/value pairs.&lt;/li&gt;
&lt;li&gt;If you request a sequence for a key, which is not present inside of the lookup table, you'll get an &lt;strong&gt;empty sequence&lt;/strong&gt;. Again, compare this behavior to Dictionary, which will throw a &lt;code&gt;KeyNotFoundException&lt;/code&gt; for non-existing keys.&lt;/li&gt;
&lt;li&gt;There is another extension method available, which is almost identical in behavior to what &lt;code&gt;ToLookup&lt;/code&gt; does. That method is &lt;code&gt;GroupBy&lt;/code&gt;. Really the only difference between these two methods is that &lt;code&gt;GroupBy&lt;/code&gt; uses deferred execution, while &lt;code&gt;ToLookup's&lt;/code&gt; execution is immediate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Additional Resources
&lt;/h3&gt;

&lt;p&gt;For a thorough deconstruction of the &lt;code&gt;ToLookup&lt;/code&gt; method, see John Skeet's great article &lt;a href="https://codeblog.jonskeet.uk/2010/12/31/reimplementing-linq-to-objects-part-18-tolookup/"&gt;Reimplementing LINQ to Objects Part 18 – ToLookup&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;As you can see, the usage of &lt;code&gt;ToLookup&lt;/code&gt; is quite versatile. My favorite use case (by far) is the ability to split up a sequence of values into 2 sequences &lt;strong&gt;using a single line of code&lt;/strong&gt; (described in the first example above).&lt;/p&gt;

&lt;p&gt;Have you ever used &lt;code&gt;ToLookup&lt;/code&gt; in your code? If yes, what was the use case? Share your thoughts in the comments!&lt;/p&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>5 Awesome Visual Studio Code Features</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Fri, 14 May 2021 12:54:23 +0000</pubDate>
      <link>https://dev.to/jdoubek/5-awesome-visual-studio-code-features-1cfh</link>
      <guid>https://dev.to/jdoubek/5-awesome-visual-studio-code-features-1cfh</guid>
      <description>&lt;p&gt;&lt;em&gt;TL;DR: Visual Studio Code is great and I highly recommend it to every developer (not only for Visual Studio classic users). If you're interested  in why I actually think it's great, read on!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm a long-term user of Visual Studio. In fact, I've been extensively using it in my jobs since the Visual Studio 6.0 release. A really long time. And I must admit that I'm more than aware of its shortcomings - slow startup times, slow project load times, occasional crashes, to name a few.&lt;/p&gt;

&lt;p&gt;Just recently I got introduced to Visual Studio Code. Not for my day-to-day job, but mostly for side projects. And I must say I fell in love with it. Its simplicity yet great extensibility and power make it perfect for quickly setting up and developing sample projects, tutorials, and, naturally, production applications too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Visual Studio Code is perfect for quickly setting up and developing sample projects, tutorials, and, naturally, production applications too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let me share with you 5 features of Visual Studio Code, which I enjoy the most and which I honestly hope were present in the classic Visual Studio too.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Visual Studio Code is blazing fast
&lt;/h3&gt;

&lt;p&gt;Speed is by far the greatest quality of Visual Studio Code. The speed of almost anything that you can do with it, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application startup&lt;/li&gt;
&lt;li&gt;Opening a workspace/folder&lt;/li&gt;
&lt;li&gt;Creating new files&lt;/li&gt;
&lt;li&gt;Using the code editor&lt;/li&gt;
&lt;li&gt;Installing and updating extensions&lt;/li&gt;
&lt;li&gt;GIT operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the list could go on.&lt;/p&gt;

&lt;p&gt;The startup speed and folder opening speed are definitely the most important for me, as I'm mostly using Visual Studio Code for smaller projects, which I need to bring up (and close) quickly. Quick code/build/debug process turnaround is also a crucial factor in my daily activities.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. No cumbersome projects, just Folders
&lt;/h3&gt;

&lt;p&gt;What? There are no projects in Visual Studio code? At first, I felt a little bit lost. As a long-term user of Visual Studio, I've been dealing with a myriad of different types and versions of projects.&lt;/p&gt;

&lt;p&gt;But then I got it - Visual Studio Code is primarily a code editor! What that means is that you just need a way of opening files and organizing them somehow. And since that organization is most of the time already present in the form of OS folders, the actual projects are redundant. As simple as that!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Visual Studio Code is primarily a code editor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, to be fair, Visual Studio classic projects are used for more than just organizing files (in fact, in the latest Visual Studio versions, some project types do not store file lists anymore). Project files also store additional configuration data, task definitions and build info. So where does all this extra configuration exist in Visual Studio Code? The answer is simple - in JSON files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debug/Run configuration is stored inside of &lt;code&gt;launch.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tasks are configured in &lt;code&gt;tasks.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Project settings are configured via &lt;code&gt;settings.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think it's a neat solution, especially since some of them (like &lt;code&gt;settings.json&lt;/code&gt;) you can create at multiple levels (user, workspace).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Powerful Extensions ecosystem
&lt;/h3&gt;

&lt;p&gt;In Visual Studio Code, extensions are an integral part of the code editor. What does that mean?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Searching for extensions and displaying extension info is fast&lt;/li&gt;
&lt;li&gt;An extension of your choice gets installed very quickly and &lt;strong&gt;without the need to restart the editor/IDE!&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You get smart suggestions for extensions that might be suitable for you and your workflow&lt;/li&gt;
&lt;li&gt;There are just a few core extensions included out-of-the-box, which means that the initial installation of Visual Studio Code is quick and does not take up unnecessary disk space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The number of available extensions and the languages/debuggers/tools that these extensions cover is astonishing. Just take a look at the list of eight of the most popular language extensions (screenshot taken on the Visual Studio Code docs &lt;a href="https://code.visualstudio.com/docs/languages/overview" rel="noopener noreferrer"&gt;Programming Languages&lt;/a&gt; page):&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faga8f6aatwfx8uk2nwnb.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faga8f6aatwfx8uk2nwnb.png" alt="VSCode extensions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if a suitable extension is not available yet? Just write your own using the &lt;a href="https://code.visualstudio.com/api" rel="noopener noreferrer"&gt;Extension API&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Integrated Terminal
&lt;/h3&gt;

&lt;p&gt;I've always been a "UI for everything" kind of guy. No wonder - with Visual Studio, you get extensive Tooling, which lets you use a fancy UI/wizard for almost anything, starting with the creation of a file or project and ending with complex build and publishing wizards.&lt;/p&gt;

&lt;p&gt;Visual Studio Code takes a different approach. A significant portion of the functionality it offers relies on command line tools. And in order to ensure that the command line tools can be executed in a quick and efficient way, Visual Studio code includes an integrated &lt;a href="https://www.hanselman.com/blog/whats-the-difference-between-a-console-a-terminal-and-a-shell" rel="noopener noreferrer"&gt;Terminal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can easily bring up a new Terminal using the &lt;code&gt;Ctrl+ `&lt;/code&gt; key combination. You can open multiple terminal windows and easily navigate between them. Visual Studio Code also lets you pick the default shell for your integrated Terminal - PowerShell, bash, etc.&lt;/p&gt;

&lt;p&gt;Overall, once you start using the Terminal to execute some common tasks and actions, you quickly realize that it is a much faster and flexible alternative to the static and often outdated UIs and wizards.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Snippets
&lt;/h3&gt;

&lt;p&gt;I've discovered Snippets in Visual Studio Code just recently, but I see great value in learning how to use and customize them.&lt;/p&gt;

&lt;p&gt;A great example of when Snippets come in handy is with the &lt;a href="https://code.visualstudio.com/docs/python/tutorial-django#_create-multiple-templates-that-extend-a-base-template" rel="noopener noreferrer"&gt;Django page templates&lt;/a&gt;. And, naturally, Snippets can be defined at both global (language) and project levels. Using project-level Snippets lets you create different templates with styles tailored to the needs of each project separately.&lt;/p&gt;

&lt;p&gt;If you're interested in discovering more about Snippets, check out the official &lt;a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets" rel="noopener noreferrer"&gt;Snippets in Visual Studio Code&lt;/a&gt; page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Are you a Visual Studio (2019) user and have you not tried Visual Studio Code yet? I highly recommend checking it out. It's worth learning - you can use it for side projects, tutorials, or maybe as a markdown editor for &lt;a href="https://johnpapa.net/how-i-write-online-articles/#1vscode" rel="noopener noreferrer"&gt;writing blog posts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What is your favorite Visual Studio Code feature? Share your experience in the comments below!&lt;/p&gt;

&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com" rel="noopener noreferrer"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>3 Easy Steps to Set Up Certificate Authentication in ASP.NET Core</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 13 Apr 2021 04:27:17 +0000</pubDate>
      <link>https://dev.to/jdoubek/3-easy-steps-to-set-up-certificate-authentication-in-asp-net-core-1ngk</link>
      <guid>https://dev.to/jdoubek/3-easy-steps-to-set-up-certificate-authentication-in-asp-net-core-1ngk</guid>
      <description>&lt;p&gt;Ever wondered how to configure a simple yet secure authentication method in ASP.NET Core? Read on!&lt;/p&gt;

&lt;p&gt;This article aims to give you a minimum set of steps necessary to configure certificate-based authentication in ASP.NET Core.&lt;/p&gt;

&lt;p&gt;At the end of the article, I'll give you a list of more detailed resources, including a link to my test GitHub repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is certificate authentication for?
&lt;/h2&gt;

&lt;p&gt;Here are a few typical scenarios that will benefit from certificate-based authentication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticating users in a corporate (intranet) environment&lt;/li&gt;
&lt;li&gt;Communication between applications or APIs&lt;/li&gt;
&lt;li&gt;Identifying IoT devices for server resources access&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Configuration steps
&lt;/h2&gt;

&lt;p&gt;Here are the 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure the server (IIS)&lt;/li&gt;
&lt;li&gt;Create and install a self-signed certificate&lt;/li&gt;
&lt;li&gt;Set up the ASP.NET Core app for certificate authentication&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step #1: Configuring IIS
&lt;/h3&gt;

&lt;p&gt;The actual validation and verification of a client certificate take place inside of IIS. We therefore need to configure IIS correctly to recognize and accept certificates.&lt;/p&gt;

&lt;p&gt;Open the IIS Manager. Find the web application which you want to configure. In the &lt;strong&gt;Features View&lt;/strong&gt; open &lt;strong&gt;SSL Settings&lt;/strong&gt;.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jip6v7jdkr05knaqp3g.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jip6v7jdkr05knaqp3g.png" title="SSL Settings" alt="SSL Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside of the SSL Settings, check the checkbox next to &lt;strong&gt;"Require SSL"&lt;/strong&gt; and select the &lt;strong&gt;"Client certificates: Require"&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;This will instruct IIS to accept (and require) client certificates and verify them before allowing the request to be passed over to our ASP.NET Core application.&lt;/p&gt;

&lt;p&gt;Note: My test setup uses &lt;code&gt;IIS&lt;/code&gt; as the host for the website. If you're using Kestrel to host your app, please, refer to the Kestrel configuration code in my &lt;a href="https://github.com/jd-cz/AspNetCertTest/blob/797f2006e55de4235fd181d7146f7d4d1786c11a/Program.cs#L24-L28" rel="noopener noreferrer"&gt;example repo&lt;/a&gt;, or check out the official &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-5.0#kestrel" rel="noopener noreferrer"&gt;Microsoft documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step #2: Installing a client certificate
&lt;/h3&gt;

&lt;p&gt;Next, we need to prepare the client certificates. The easiest option would be using certificates issued by a browser-trusted CA (GoDaddy, Comodo, etc.). In the case of an intranet application however, we can just safely go with self-signed certificates.&lt;/p&gt;

&lt;p&gt;We'll accomplish the self-signed certificate installation in 2 steps. In the first step, we'll issue a new self-signed client certificate. The second step will then make the certificate trusted on the webserver.&lt;/p&gt;

&lt;p&gt;Here is a PowerShell script to generate a new self-signed client certificate (valid for two years) and store it in the user's personal certificates store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;New-SelfSignedCertificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-certstorelocation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cert:\CurrentUser\my&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-Subject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test User"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FriendlyName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test client certificate"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-NotAfter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddYears&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-KeyUsageProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Sign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-KeyUsage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CertSign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CRLSign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DigitalSignature&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the User Certificates control panel you can now observe that a new certificate has been created inside of the &lt;code&gt;Personal&lt;/code&gt; certificates store:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flo2jc9d10o7qk073inbh.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flo2jc9d10o7qk073inbh.png" title="Client certificate" alt="Client certificate"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From here you can export the public key of the client certificate into a &lt;code&gt;.cer&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;On the webserver, where IIS is installed, you have to install the certificate stored in the CER file, placing it into the Computer Certificates' &lt;code&gt;Trusted roots&lt;/code&gt; store.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftx4aeewyv8s70fqwxoji.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftx4aeewyv8s70fqwxoji.png" title="Trusted roots store" alt="Trusted roots store"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! We have prepared the client certificate, making it ready to be used on both client and server sides.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step #3: ASP.NET Core authentication setup
&lt;/h3&gt;

&lt;p&gt;Lastly, we are going to set up certificate authentication in our ASP.NET Core application.&lt;/p&gt;

&lt;p&gt;The support for certificate authentication resides in a separate NuGet package. Therefore, let's first add the &lt;code&gt;Microsoft.AspNetCore.Authentication.Certificate&lt;/code&gt; package to our app.&lt;/p&gt;

&lt;p&gt;Now that we have support for certificates added, the only step remaining is correctly configuring our authentication pipeline. We do that by including the following code in our &lt;code&gt;Startup.ConfigureServices&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAuthentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CertificateAuthenticationDefaults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticationScheme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCertificate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowedCertificateTypes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CertificateTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;All&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;There are several options that allow fine-tuning the behavior of the certificate authentication handler. In our case, we only changed the &lt;code&gt;AllowedCertificateTypes&lt;/code&gt; option, to accept both chained and self-signed certificates (by default, only chained certificates are accepted).&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;Microsoft.AspNetCore.Authentication.Certificate&lt;/code&gt; package has been introduced in ASP.NET Core v3.0. If you're using a version of ASP.NET Core older than 3.0, you have to resort to a compatibility package created by &lt;a href="https://github.com/blowdart" rel="noopener noreferrer"&gt;Barry Dorrans&lt;/a&gt; named &lt;code&gt;idunno.Authentication.Certificate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, don't forget to actually add the authentication middleware to your ASP.NET Core request processing pipeline. Do this inside of the &lt;code&gt;Startup.Configure&lt;/code&gt; method implementation:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseAuthentication&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Seeing it in action
&lt;/h2&gt;

&lt;p&gt;When the Web API is called from a browser (e.g. Chrome), you are asked to provide a client certificate:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjds5yfpmiopinl95xok.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjds5yfpmiopinl95xok.png" alt="cert-auth-select-certificate.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The webserver will then validate the certificate and if OK, the request will be sent to your ASP.NET Core Web API. The example response will look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Test API call successful! Certificate Subject Name: Test User
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If on the other hand you do not specify a certificate, or you select an invalid/untrusted certificate, you'll receive an error response:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;HTTP Error 403
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;ERR_BAD_SSL_CLIENT_AUTH_CERT
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Check out the full sample in my GitHub repo:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jd-cz" rel="noopener noreferrer"&gt;
        jd-cz
      &lt;/a&gt; / &lt;a href="https://github.com/jd-cz/AspNetCertTest" rel="noopener noreferrer"&gt;
        AspNetCertTest
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AspNetCertTest&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;This is a sample repo for my blog post &lt;a href="https://mydevtricks.com/certificate-authentication-in-aspnet-core" rel="nofollow noopener noreferrer"&gt;3 Easy Steps to Set Up Certificate Authentication in ASP.NET Core&lt;/a&gt;. The example uses Kestrel as a server host for the ASP.NET Core application.&lt;/p&gt;

&lt;p&gt;Check out the article on my blog &lt;a href="https://mydevtricks.com/" rel="nofollow noopener noreferrer"&gt;My Dev Tricks&lt;/a&gt; for details.&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jd-cz/AspNetCertTest" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  Other resources
&lt;/h2&gt;

&lt;p&gt;Microsoft Docs article describing Certificate Authentication:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-5.0" rel="noopener noreferrer"&gt;Configure certificate authentication in ASP.NET Core&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A neat article explaining the general benefits of using certificate-based authentication:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.globalsign.com/en/blog/what-is-certificate-based-authentication" rel="noopener noreferrer"&gt;What Is Certificate-Based Authentication and Why Should I Use It?&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Use these 3 easy steps and you'll secure access to your ASP.NET Core controllers by letting only the clients holding the client certificate invoke the controller functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: For an even more secure setup, you can play with the various options available to the &lt;code&gt;AddCertificate()&lt;/code&gt; call, for example implementing custom validation based on a certificate property.&lt;/p&gt;

&lt;p&gt;Do you find authentication using client certificates useful? Let me know in the comments. Also, if you enjoyed this article, please, share it with your friends and colleagues!&lt;/p&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com" rel="noopener noreferrer"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>security</category>
      <category>asp</category>
    </item>
    <item>
      <title>LINQ gems: Troubles with Out Parameters</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Fri, 26 Mar 2021 05:14:45 +0000</pubDate>
      <link>https://dev.to/jdoubek/linq-gems-troubles-with-out-parameters-4bp9</link>
      <guid>https://dev.to/jdoubek/linq-gems-troubles-with-out-parameters-4bp9</guid>
      <description>&lt;p&gt;How do you deal with &lt;code&gt;out&lt;/code&gt; parameters inside of LINQ queries?&lt;/p&gt;

&lt;p&gt;Almost every time I come across the need to invoke a method inside of a LINQ query, which uses an &lt;code&gt;out&lt;/code&gt; argument, I need to stop for a moment and think about what the correct solution is. And unfortunately, there does not seem to be a solution, which is the &lt;em&gt;obviously right&lt;/em&gt; one.&lt;/p&gt;

&lt;p&gt;One of the typical examples of consuming an &lt;code&gt;out&lt;/code&gt; variable is when accessing the elements of a Dictionary using the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.trygetvalue?view=net-5.0"&gt;TryGetValue&lt;/a&gt; method. In the sample code I'll be using below, we have a dictionary of common English words together with their usage counts (perhaps extracted from a piece of text somewhere). We then declare an array of test words, for which we want to obtain their usage count (and eventually sort by it).&lt;/p&gt;

&lt;h3&gt;
  
  
  Using a local variable
&lt;/h3&gt;

&lt;p&gt;Using a local variable is probably the first thing that a developer will try:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Dictionary&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;,&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="n"&gt;wordUsage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&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;,&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="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"hello"&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="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&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;testWords&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="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"case"&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;usageVar&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;testWords&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wordFound&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wordUsage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;usageVar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usageVar&lt;/span&gt;&lt;span class="p"&gt;);&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&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;$"Word: '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' is repeated &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; time(s)."&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;So far, everything works as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Word: 'hello' is repeated 100 time(s).
Word: 'world' is repeated 20 time(s).
Word: 'use' is repeated 75 time(s).
Word: 'case' is repeated 10 time(s).
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we now however add a request to sort the output by the usage count:&lt;br&gt;
&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;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;testWords&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;wordFound&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wordUsage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;usageVar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;orderby&lt;/span&gt; &lt;span class="n"&gt;usageVar&lt;/span&gt;
  &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usageVar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things start to break apart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Word: 'hello' is repeated 10 time(s).
Word: 'world' is repeated 10 time(s).
Word: 'use' is repeated 10 time(s).
Word: 'case' is repeated 10 time(s).
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Because &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=net-5.0"&gt;OrderBy&lt;/a&gt; requires the whole sequence to be processed, before it can perform a sort on the elements of the sequence. What it means is that the &lt;code&gt;let&lt;/code&gt; projection will execute on all elements in our sample set  and the very last processed element in the set (the word 'hello') will assign a value of '10' to the local variable &lt;code&gt;usageVar&lt;/code&gt;. This value is then passed four times into the &lt;code&gt;orderby&lt;/code&gt; statement. Which is obviously &lt;em&gt;wrong&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, using a local variable is clearly not the way to go.&lt;/strong&gt; What are the alternatives then?&lt;/p&gt;

&lt;h3&gt;
  
  
  Local function
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#local-functions"&gt;Local functions&lt;/a&gt; are a concept introduced in C# 7.0. They let you declare a method inside the body of another method. What we can therefore do is create a simple helper method, which establishes a local scope for the &lt;code&gt;out&lt;/code&gt; variable needed by the &lt;code&gt;TryParse&lt;/code&gt; method, thus making the usage of the local variable safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;void&lt;/span&gt; &lt;span class="nf"&gt;OutTestUsingLocalFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Dictionary&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;,&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="n"&gt;wordUsage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&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;,&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="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"hello"&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="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;  &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;75&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"case"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&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;testWords&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="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"world"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"case"&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;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
      &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;testWords&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetWordUsageCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wordUsage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;orderby&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;
      &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;);&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query&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;$"Word: '&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;' is repeated &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; time(s)."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;GetWordUsageCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&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;,&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="n"&gt;wordUsageDic&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;word&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;wordUsageDic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;val&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we get the expected (sorted) output!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Word: 'case' is repeated 10 time(s).
Word: 'world' is repeated 20 time(s).
Word: 'use' is repeated 75 time(s).
Word: 'hello' is repeated 100 time(s).
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that in case you're still on an earlier version of C#, you could use a normal (most likely private) class method instead of a local method. If local functions are available though, I personally prefer them, since they help prevent classes from getting polluted with too many single-purpose helper methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Value Tuple
&lt;/h3&gt;

&lt;p&gt;Just recently I came across a neat solution, which involves creating a &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/value-tuples"&gt;value tuple&lt;/a&gt; as a container for the local &lt;code&gt;out&lt;/code&gt; variable. Note though that this code is also C# 7.0+ only, as it requires &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7#out-variables"&gt;declaring the out variable in the argument list of a method&lt;/a&gt;.&lt;br&gt;
&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;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;testWords&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="p"&gt;=&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="n"&gt;wordUsage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;localIntVar&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;localIntVar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;orderby&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This solution will also scale nicely when the invoked method declares multiple &lt;code&gt;out&lt;/code&gt; variables.&lt;/p&gt;

&lt;p&gt;As a side note - using a value tuple inside of a query would be even easier when combined with &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/deconstruct"&gt;tuple deconstruction&lt;/a&gt;. Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;let&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="n"&gt;usage&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="n"&gt;wordUsage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryGetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;localIntVar&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;localIntVar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, tuple deconstruction in LINQ queries is not supported at the moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;error CS1001: Identifier expected
error CS1003: Syntax error, '=' expected
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe we'll get that supported in one of the future C# versions (more info in this &lt;a href="https://github.com/dotnet/csharplang/discussions/355"&gt;discussion&lt;/a&gt; on GitHub).&lt;/p&gt;

&lt;h3&gt;
  
  
  Future
&lt;/h3&gt;

&lt;p&gt;If you're interested in some of the latest development around local parameters in LINQ queries, check out the following postings in the &lt;a href="https://github.com/dotnet/csharplang"&gt;csharplang&lt;/a&gt; GitHub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/dotnet/csharplang/discussions/159"&gt;Proposal: Support out/pattern variables in LINQ with query-scoping #159&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/dotnet/roslyn/issues/15619"&gt;Extend Out Variable support to LINQ #15619&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;To sum it up, if you have a need to consume an &lt;code&gt;out&lt;/code&gt; variable inside of a LINQ query, use one of these options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single-purpose local function (or a private class method)&lt;/li&gt;
&lt;li&gt;A helper value tuple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do NOT use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A local variable (unless you really know what you're doing), as it may produce incorrect results&lt;/li&gt;
&lt;li&gt;An out variable declared inside of the argument list of a method call, as that is currently not supported inside of LINQ queries&lt;/li&gt;
&lt;li&gt;A deconstructed value tuple - tuple deconstruction is currently not supported in LINQ queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is &lt;strong&gt;your&lt;/strong&gt; experience with &lt;code&gt;out&lt;/code&gt; variables in LINQ queries?&lt;/p&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>linq</category>
    </item>
    <item>
      <title>What it takes to be a Software Engineer</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 16 Mar 2021 12:41:19 +0000</pubDate>
      <link>https://dev.to/jdoubek/what-it-takes-to-be-a-software-engineer-5a00</link>
      <guid>https://dev.to/jdoubek/what-it-takes-to-be-a-software-engineer-5a00</guid>
      <description>&lt;p&gt;People often wonder (and argue) what is the exact role of a Software Engineer and maybe even more what is the difference in responsibilities between a Software Engineer vs. Software Developer. This is a broadly discussed topic and people often have highly differing opinions.&lt;/p&gt;

&lt;p&gt;With this post, I'm not making an attempt to compile a comprehensive list of all materials available on the topic. I'm merely giving my own, entirely subjective view, based on my past experiences.&lt;/p&gt;

&lt;p&gt;OK, let's dive right into it...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The core quality of a Software Engineer is that he/she is capable of fulfilling other roles in the product development life cycle, other than just developing code. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is my compilation of the additional roles:&lt;/p&gt;

&lt;h3&gt;
  
  
  Requirements and Planning
&lt;/h3&gt;

&lt;p&gt;Participates in creating or refining requirements.&lt;/p&gt;

&lt;p&gt;Meets with the Product Owner and helps him/her understand technical aspects of the developed solution.&lt;/p&gt;

&lt;p&gt;Helps with creating both LOE and detailed estimates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Design and Architecture
&lt;/h3&gt;

&lt;p&gt;Creates models, diagrams and if necessary, defines APIs.&lt;/p&gt;

&lt;p&gt;Has a good overview of available technologies and design principles, in order to be able to come up with technology proposals which are best suited for each part of the developed product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Research
&lt;/h3&gt;

&lt;p&gt;Does research on various types and levels of tasks, starting with simple development impediments (solvable by a stack overflow search), ending with a thorough analysis of a technology, API or library to be used for a new product or feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Development
&lt;/h3&gt;

&lt;p&gt;A software engineer's knowledge is not limited by one application "tier" (client, server, database), programming language or technology stack. The grasp should be broad, giving him or her the ability to tackle or at least understand all the tasks and challenges which may arise during the application development lifecycle.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging and Troubleshooting
&lt;/h3&gt;

&lt;p&gt;Understands how to use different debugging, profiling and troubleshooting tools and techniques.&lt;/p&gt;

&lt;h3&gt;
  
  
  DBA
&lt;/h3&gt;

&lt;p&gt;Maintains development and testing environments (e.g. SQL Server instances).&lt;/p&gt;

&lt;p&gt;Troubleshoots performance of queries and stored procedures.&lt;/p&gt;

&lt;p&gt;Understands database schemas, knowing how to generate database change scripts and scripts for shuffling data around.&lt;/p&gt;

&lt;h3&gt;
  
  
  DevOps
&lt;/h3&gt;

&lt;p&gt;Sets up and manages builds and deployments.&lt;/p&gt;

&lt;p&gt;Sets up and manages development, test and staging environments.&lt;/p&gt;

&lt;p&gt;Recognizes the benefits of continuous delivery and knows how to implement it.&lt;/p&gt;

&lt;h3&gt;
  
  
  QA and Testing
&lt;/h3&gt;

&lt;p&gt;Helps QA with spotting and identifying bugs.&lt;/p&gt;

&lt;p&gt;Writes bug descriptions, including sensible steps to reproduce.&lt;/p&gt;

&lt;p&gt;Quickly creates sample and test projects to help others with troubleshooting.&lt;/p&gt;

&lt;p&gt;Effectively communicates with the QA team (leaving unnecessary emotions aside).&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Understands the importance of documentation, starting with code comments and ending with comprehensive user guides.&lt;/p&gt;

&lt;p&gt;Has solid writing skills, able to express development-level knowledge of a certain topic in a user-friendly way.&lt;/p&gt;

&lt;p&gt;Uses tools for auto-generating API documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mentoring
&lt;/h3&gt;

&lt;p&gt;Helps other software developers with solving their issues.&lt;/p&gt;

&lt;p&gt;Participates in onboarding newly hired colleagues.&lt;/p&gt;

&lt;p&gt;Prepares technically oriented "lunch and learn" (or similar) sessions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiring process
&lt;/h3&gt;

&lt;p&gt;Carries out resume-based and phone screening of candidates.&lt;/p&gt;

&lt;p&gt;Participates in the interview process, evaluating the candidate's attitude, aptitude and technical abilities.&lt;/p&gt;

&lt;p&gt;Gives valuable feedback to the manager to help him/her decide on whether to hire or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  3rd level support
&lt;/h3&gt;

&lt;p&gt;Has solid communication skills to be able to effectively communicate with the tech support staff, or sometimes directly with the customer/end-user.&lt;/p&gt;

&lt;p&gt;Reproduces and troubleshoots issues from (sometimes) partial or unclear descriptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  IT
&lt;/h3&gt;

&lt;p&gt;Has a solid understanding of the hardware and software that he/she is using and can maintain and troubleshoot it (to a certain level).&lt;/p&gt;

&lt;p&gt;Has enough knowledge about basic security principles and ways how to mitigate security risks and vulnerabilities.&lt;/p&gt;

&lt;p&gt;Is able to effectively fix most hardware and software errors by "turning it off and on again". 😉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E1lZOtjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media4.giphy.com/media/rcOlpTCkM1GAE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E1lZOtjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media4.giphy.com/media/rcOlpTCkM1GAE/giphy.gif" alt="Off And On Again GIFs - Get the best GIF on GIPHY"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Again, the list above is highly subjective and by no means comprehensive. To me though, each of these skills represents something that requires a software engineer to go a step further from what is traditionally requested from the software developer role.&lt;/p&gt;

&lt;p&gt;What is your experience? Would you add something? Please, comment!&lt;/p&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>LINQ gems: Left Outer Join</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Thu, 12 Nov 2020 12:50:16 +0000</pubDate>
      <link>https://dev.to/jdoubek/linq-gems-left-outer-join-58md</link>
      <guid>https://dev.to/jdoubek/linq-gems-left-outer-join-58md</guid>
      <description>&lt;p&gt;Doing a left outer join in T-SQL is as straightforward as adding a single keyword to the &lt;a href="https://docs.microsoft.com/en-us/sql/t-sql/queries/from-transact-sql?view=sql-server-ver15#joined-table"&gt;JOIN statement&lt;/a&gt;. I remember that when I first tried to perform a left outer join in a LINQ query, I was honestly surprised about how confusing the syntax was. Even now, after years of using it, I sometimes hesitate while trying to remember the exact syntax.&lt;/p&gt;

&lt;p&gt;In LINQ, the left outer join is accomplished in 2 phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Performing a &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-grouped-joins"&gt;group join&lt;/a&gt; between the first and second collection&lt;/li&gt;
&lt;li&gt;Running the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.defaultifempty?view=netframework-4.8"&gt;Enumerable.DefaultIfEmpty&lt;/a&gt; extension method on the expanded group join results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A true left outer join "experience" can only be accomplished by executing both steps. The group join by itself however produces very similar results and sometimes it may even be a better option than doing the actual left outer join.&lt;/p&gt;

&lt;p&gt;Let's first have a look at just the group join.&lt;/p&gt;

&lt;h3&gt;
  
  
  Group Join
&lt;/h3&gt;

&lt;p&gt;One easy way of how to accomplish a behavior similar to a left outer join is using the group join. The group join simply pairs elements from the first (left) collection with a set of matching elements from the second (right) collection, producing a correlated subset of right elements for each member of the left collection. If there are no correlated elements found for a member of the left collection, the sequence of correlated elements is empty.&lt;/p&gt;

&lt;p&gt;Even though this is not a true left outer join (as known from the SQL syntax), the group join is often quite useful and, to be honest, many times I'd wish that this type of join was (in some form) available in T-SQL as well.&lt;/p&gt;

&lt;p&gt;Consider this example where a collection of days in a week is joined to another collection containing delivery times for a particular day. We're interested in outputting all of the days, regardless of whether a delivery exists for that day or not. For that reason, we're using a group join here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Test data&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&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;deliveries&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"8AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"10AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"2PM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Group Join&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;
    &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;equals&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Output&lt;/span&gt;
&lt;span class="n"&gt;query&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="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; deliveries: &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;Join&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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;)&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Produces the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Mon deliveries: 8AM
Tue deliveries:
Wed deliveries:
Thu deliveries: 10AM, 2PM
Fri deliveries:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see in the output, the days without any deliveries are preserved, so the concept of left outer join is maintained. In addition, we get a linked sub-collection containing the matching delivery times, which can then be easily processed, in our case using &lt;em&gt;string.Join()&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Left Outer Join
&lt;/h3&gt;

&lt;p&gt;To accomplish the full behavior of a left outer join, we still start with a group join. In addition though we need to expand the results of the group join and process it further using the &lt;em&gt;DefaultIfEmpty&lt;/em&gt; method. &lt;em&gt;DefaultIfEmpty&lt;/em&gt; ensures that each item in the left collection is included in the result set even when that element has no matches in the right collection.&lt;/p&gt;

&lt;p&gt;Following is a modification of the first example, this time with a call to &lt;em&gt;DefaultIfEmpty&lt;/em&gt; included in order to produce an actual left outer join:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Test data&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&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;deliveries&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"8AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"10AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"2PM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Left Outer Join&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;equals&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;
        &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dayDelivery&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DefaultIfEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dayDelivery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output&lt;/span&gt;
&lt;span class="n"&gt;q&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="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; delivery: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Mon delivery: 8AM
Tue delivery:
Wed delivery:
Thu delivery: 10AM
Thu delivery: 2PM
Fri delivery:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unlike with the group join, with left outer join we get duplicate rows for Thursday, as there are multiple deliveries scheduled for Thursday. This is the main difference, which needs to be considered when making the choice between a group join and left outer join.&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding Indexed Select
&lt;/h4&gt;

&lt;p&gt;Looking at the output of the previous example, I think it would be nice if multiple deliveries for the same day would be ranked. Which is a perfect usage scenario for the Indexed Select presented in my &lt;a href="https://dev.to/jdoubek/linq-gems-indexed-select-iie"&gt;previous post&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Test data&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&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;deliveries&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"8AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"10AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"2PM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Left Outer Join + Indexed Select&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;equals&lt;/span&gt; &lt;span class="n"&gt;delv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;into&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;numDayDelvs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dayDelvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;deliveredDay&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numDayDelvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DefaultIfEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveredDay&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deliveredDay&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output&lt;/span&gt;
&lt;span class="n"&gt;q&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="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&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="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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; delivery #&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&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="s"&gt;: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&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="k"&gt;else&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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; delivery:"&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;Gives us a ranked output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;Mon delivery #&lt;/span&gt;1: 8AM
&lt;span class="go"&gt;Tue delivery:
Wed delivery:
&lt;/span&gt;&lt;span class="gp"&gt;Thu delivery #&lt;/span&gt;1: 10AM
&lt;span class="gp"&gt;Thu delivery #&lt;/span&gt;2: 2PM
&lt;span class="go"&gt;Fri delivery:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could of course further enhance the example by only showing the rank for days, which have more than one delivery assigned. I'll leave that as an exercise for the reader.&lt;/p&gt;

&lt;h3&gt;
  
  
  Alternative syntax
&lt;/h3&gt;

&lt;p&gt;There is an alternative syntax for the left outer join. It also uses the &lt;em&gt;DefaultIfEmpty&lt;/em&gt; method, but the syntax is a bit more readable.&lt;/p&gt;

&lt;p&gt;Let's take the previous example and rewrite it a little bit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Test data&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&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;deliveries&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"8AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"10AM"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"2PM"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Left Outer Join using alternative syntax&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dayDelivery&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deliveries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;DefaultIfEmpty&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dayDelivery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Output&lt;/span&gt;
&lt;span class="n"&gt;q&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="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; delivery: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;time&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get exactly the same output that we got when using the standard left outer join syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Mon delivery: 8AM
Tue delivery:
Wed delivery:
Thu delivery: 10AM
Thu delivery: 2PM
Fri delivery:
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you may wonder why this alternative syntax is not the recommended way of doing a left outer join in LINQ? Well, the answer is fairly simple - for performance reasons. If you run the alternative query in a pure LINQ-To-Objects scenario (such as the scenario I use in my examples), &lt;strong&gt;you won't get any caching of data&lt;/strong&gt;; the second collection will be scanned (iterated through entirely) several times. This is fine for small data sets, but for large collections, it could easily become an unnecessary performance hog.&lt;/p&gt;

&lt;p&gt;For database-driven LINQ providers though, this approach represents an equally effective syntax for writing a left outer join. Simply because the DB provider is usually capable of recognizing the alternative syntax and &lt;strong&gt;translating it into a standard left outer join SQL statement&lt;/strong&gt;. For example, when using the Entity Framework Core SQL Server Provider, the generated SQL query is the same for both the standard and alternative left outer join LINQ syntaxes.&lt;/p&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>linq</category>
    </item>
    <item>
      <title>LINQ gems: Indexed Select</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Wed, 28 Oct 2020 09:39:58 +0000</pubDate>
      <link>https://dev.to/jdoubek/linq-gems-indexed-select-iie</link>
      <guid>https://dev.to/jdoubek/linq-gems-indexed-select-iie</guid>
      <description>&lt;p&gt;Here's another LINQ gem, which is very useful if you plan to base your projection or filtering logic on the &lt;strong&gt;element's index in a sequence&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;From the MSDN page for &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netframework-4.8#System_Linq_Enumerable_Select__2_System_Collections_Generic_IEnumerable___0__System_Func___0_System_Int32___1__"&gt;Enumerable.Select&lt;/a&gt;():&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Projects each element of a sequence into a new form by incorporating the element's index.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What the "incorporating the element's index" part means is that you get an extra parameter inside of the &lt;em&gt;Select&lt;/em&gt; method's selector, which gets incremented with each processed element. As is common in C#, the index is zero-based.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Let's have a look at a simple example, which outputs the sequence numbers of days in a week (apologies to all readers, for whom Monday is not the first day of the week 😊).&lt;br&gt;
&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;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sun"&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;daysOutput&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;day&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is day number: &lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="n"&gt;index&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="s"&gt;"&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="n"&gt;daysOutput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="p"&gt;=&amp;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="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When executed, the output will be the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Mon is day number: 1
Tue is day number: 2
Wed is day number: 3
Thu is day number: 4
Fri is day number: 5
Sat is day number: 6
Sun is day number: 7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  or...
&lt;/h3&gt;

&lt;p&gt;Let's just simply generate a sequence number for an array of values and project it into an array for whatever usage may be appropriate.&lt;br&gt;
&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;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sun"&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;indexedDays&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Day&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Index&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How about query expression syntax?
&lt;/h3&gt;

&lt;p&gt;There is no query expression syntax for this overload of the &lt;em&gt;Select&lt;/em&gt; method. However, one can simply embed the indexed &lt;em&gt;Select&lt;/em&gt; overload inside of the query expression:&lt;br&gt;
&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;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sun"&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;weekendDays&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&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="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;6&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enumerable.Where()
&lt;/h3&gt;

&lt;p&gt;There is an indexed overload available for the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.where?view=netframework-4.8#System_Linq_Enumerable_Where__1_System_Collections_Generic_IEnumerable___0__System_Func___0_System_Int32_System_Boolean__"&gt;Enumerable.Where()&lt;/a&gt; extension method too. Using &lt;em&gt;Where&lt;/em&gt; instead of &lt;em&gt;Select&lt;/em&gt;, the previous example can be further simplified:&lt;br&gt;
&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;days&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="s"&gt;"Mon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Tue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Wed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Thu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Fri"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Sun"&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;weekendDays&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;day&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&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;index&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// (index+1) &amp;gt;= 6&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Other useful applications
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Selecting each N-th element in a sequence&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ordering based on element position&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coordination across multiple sequences&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>linq</category>
    </item>
    <item>
      <title>LINQ gems: Zip</title>
      <dc:creator>Jan Doubek</dc:creator>
      <pubDate>Tue, 20 Oct 2020 13:30:34 +0000</pubDate>
      <link>https://dev.to/jdoubek/linq-gems-zip-enn</link>
      <guid>https://dev.to/jdoubek/linq-gems-zip-enn</guid>
      <description>&lt;p&gt;I'm always fascinated by how simple yet helpful LINQ queries are.&lt;/p&gt;

&lt;p&gt;Take for example the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.zip"&gt;Enumerable.Zip()&lt;/a&gt; method. It's simple, yet very useful in case you need to &lt;strong&gt;combine two sequences of data&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Here's a partial example where Zip() is used to combine a sequence of original text resources with their translations (produced for example by the &lt;a href="https://cloud.google.com/translate/docs"&gt;Google Cloud Translation API&lt;/a&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&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="n"&gt;ResourceText&lt;/span&gt; &lt;span class="n"&gt;text&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;translation&lt;/span&gt;&lt;span class="p"&gt;)&amp;gt;&lt;/span&gt; 
    &lt;span class="nf"&gt;TranslateResourceTexts&lt;/span&gt;&lt;span class="p"&gt;(&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="n"&gt;ResourceText&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resourceTexts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Grab just the strings to translate&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="n"&gt;strings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resourceTexts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Translate the strings (call Google Translate V3 API)&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="n"&gt;translatedStrings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;TranslateStrings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Combine the two sequences, producing an enumerable of tuples &lt;/span&gt;
    &lt;span class="c1"&gt;// containing both the original resource text and its translation&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resourceTexts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;translatedStrings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;translation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
                             &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;translation&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;Simple and easily readable. &lt;/p&gt;

&lt;p&gt;As with most of the LINQ functions, I could of course accomplish the same with a &lt;em&gt;for&lt;/em&gt; or &lt;em&gt;for each&lt;/em&gt; loop and a few extra lines of code. However, in most cases, I consider the use of LINQ syntax a cleaner alternative.&lt;/p&gt;

&lt;p&gt;Final notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Zip() method can only be called using the &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/query-syntax-and-method-syntax-in-linq"&gt;LINQ method syntax&lt;/a&gt;, there's no query syntax option for it.&lt;/li&gt;
&lt;li&gt;It is available starting with .NET Framework 4.0.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you find this post interesting, be sure to check out other posts on my blog &lt;a href="https://mydevtricks.com"&gt;mydevtricks.com&lt;/a&gt;.&lt;/p&gt;

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