<?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: Ahmed Tarek Hasan</title>
    <description>The latest articles on DEV Community by Ahmed Tarek Hasan (@ahmedtarekhasan).</description>
    <link>https://dev.to/ahmedtarekhasan</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%2F738941%2Fb730cddf-58d0-48ff-8383-5621057af2a6.jpeg</url>
      <title>DEV Community: Ahmed Tarek Hasan</title>
      <link>https://dev.to/ahmedtarekhasan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmedtarekhasan"/>
    <language>en</language>
    <item>
      <title>🚀 Official Launch of DSP Community 🎉</title>
      <dc:creator>Ahmed Tarek Hasan</dc:creator>
      <pubDate>Tue, 09 Jan 2024 15:54:40 +0000</pubDate>
      <link>https://dev.to/ahmedtarekhasan/official-launch-of-dsp-community-1obp</link>
      <guid>https://dev.to/ahmedtarekhasan/official-launch-of-dsp-community-1obp</guid>
      <description>&lt;p&gt;I am thrilled to share with you the official launch of my new software engineering website, blog, and community.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.developmentsimplyput.com/" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--W5hRLPPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fit/w_2500%2Ch_1330%2Cal_c/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" height="250" class="m-0" width="250"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.developmentsimplyput.com/" rel="noopener noreferrer" class="c-link"&gt;
          
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Development Simply Put, your ultimate destination for software engineering excellence. Explore insightful blog posts and articles covering industry trends. Engage in interactive quizzes to test your knowledge, and master the craft with comprehensive tutorials. Elevate your skills with expert tips, tricks, hints, and best practices. Dive into design patterns to create robust solutions. Join our vibrant community and stay ahead in the dynamic world of software engineering.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vch4z5LY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fill/w_192%252Ch_192%252Clg_1%252Cusm_0.66_1.00_0.01/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" width="192" height="192"&gt;
        developmentsimplyput.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;A space that goes beyond a traditional blog to become a thriving software engineering community!&lt;/p&gt;




&lt;p&gt;After a lot of hard work and dedication, I’ve finally launched my website and blog to provide you with the latest insights, tips, and resources in the world of software engineering. I’ve also taken the time to republish my previous articles on the new blog.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.developmentsimplyput.com/blog" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--0ZFoMMLq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%7Emv2.png/v1/fill/w_250%2Ch_250%2Cal_c/488a99_da18697d4b2740e487b6f5793e982d64%7Emv2.png" height="250" class="m-0" width="250"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.developmentsimplyput.com/blog" rel="noopener noreferrer" class="c-link"&gt;
          
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Software blog with articles and posts about all aspects of Software Engineering, Architecture, Development, Programming, and Coding. Here you can find best practices, explanations, tutorials, guides, tips, hints, code samples, and more.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vch4z5LY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fill/w_192%252Ch_192%252Clg_1%252Cusm_0.66_1.00_0.01/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" width="192" height="192"&gt;
        developmentsimplyput.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;However, please keep in mind, this project has been a labor of love, and I’m excited to turn it into more than just a blog. My vision is to cultivate a thriving community where collaboration and innovation take center stage.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 What Inspired Me
&lt;/h2&gt;

&lt;p&gt;Years ago, Albert Einstein’s timeless words became my guiding principle:&lt;/p&gt;

&lt;p&gt;If you can’t explain it simply, you don’t understand it well enough.&lt;/p&gt;

&lt;p&gt;This simple yet profound statement sparked my journey into blogging and writing technical content, fulfilling my passion for learning and sharing knowledge which eventually helps me learn more.&lt;/p&gt;

&lt;p&gt;However, as the days passed, I yearned for more. It dawned on me — what about the other dimensions of my life as a software engineer? How do I socialize, generate new ideas, present myself better? After that realization, it was so obvious what to call my initiative; “Development Simply Put”. Contrary to common perception — even among those close to me — it was never about Software Engineering Development; it was always about Software Engineers Development.&lt;/p&gt;




&lt;h2&gt;
  
  
  👥 Join the Community
&lt;/h2&gt;

&lt;p&gt;Discover a space that goes beyond traditional blogging. The website aims to foster connections, discussions, and collaborations within the dynamic world of software engineering.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 What’s in Store
&lt;/h2&gt;

&lt;p&gt;I have big plans for the future, including engaging activities, collaborative projects, and opportunities for community members to shine. Stay tuned for exciting developments!&lt;/p&gt;




&lt;p&gt;Development Simply Put DSP Community Blog Posts Articles Tips Hints Tricks Tutorials Quizzes Evaluations Projects .NET DotNet C# CSharp Code Coding Programming Software Design Development Engineering Architecture Best Practice Ahmed Tarek&lt;/p&gt;




&lt;h2&gt;
  
  
  📬 Subscribe to Stay Connected
&lt;/h2&gt;

&lt;p&gt;Be part of this journey from the start by subscribing to my newsletter. Get the latest updates directly in your inbox and be the first to know about upcoming community initiatives.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.developmentsimplyput.com/subscribe" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--W5hRLPPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fit/w_2500%2Ch_1330%2Cal_c/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" height="250" class="m-0" width="250"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.developmentsimplyput.com/subscribe" rel="noopener noreferrer" class="c-link"&gt;
          
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Subscribe to Development Simply Put to get articles and posts about all aspects of Software Engineering, Architecture, Development, Programming, and Coding. You would get best practices, explanations, tutorials, guides, tips, hints, code samples, and more.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vch4z5LY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fill/w_192%252Ch_192%252Clg_1%252Cusm_0.66_1.00_0.01/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" width="192" height="192"&gt;
        developmentsimplyput.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  💡 How You Can Support
&lt;/h2&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;&lt;a href="https://www.developmentsimplyput.com/subscribe"&gt;Subscribe&lt;/a&gt;&lt;/strong&gt;: Receive great content and be a part of the community from day one.&lt;br&gt;
2️⃣ Engage: Read, rate, and comment on &lt;strong&gt;&lt;a href="https://www.developmentsimplyput.com/blog"&gt;blog articles&lt;/a&gt;&lt;/strong&gt; to fuel discussions.&lt;br&gt;
3️⃣ Share: Spread the knowledge by sharing articles on social media.&lt;br&gt;
4️⃣ Spread the Word: Help grow our community by sharing this announcement.&lt;br&gt;
5️⃣ &lt;strong&gt;&lt;a href="https://www.developmentsimplyput.com/support-us"&gt;Other ways…&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🗣 Your Voice Matters
&lt;/h2&gt;

&lt;p&gt;Your support is crucial in making this vision a reality, and I can’t wait to build a vibrant community together. I invite you to share your thoughts, suggestions, and topics you’d like to see covered. Let’s build this community together!&lt;/p&gt;

&lt;p&gt;Thank you for being a part of this exciting journey! 🚀&lt;/p&gt;



&lt;p&gt;🎁Presents&lt;br&gt;
Don’t forget to check our &lt;strong&gt;Free Udemy Coupons&lt;/strong&gt; Page.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.developmentsimplyput.com/udemy-coupons" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--W5hRLPPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fit/w_2500%2Ch_1330%2Cal_c/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" height="250" class="m-0" width="250"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.developmentsimplyput.com/udemy-coupons" rel="noopener noreferrer" class="c-link"&gt;
          
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          LinkedIn group which shares free coupons for Udemy courses on different fields of knowledge. The main goal of this initiative is to encourage people to persist a daily habit of learning new skills rather than doing it occasionally.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vch4z5LY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fill/w_192%252Ch_192%252Clg_1%252Cusm_0.66_1.00_0.01/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" width="192" height="192"&gt;
        developmentsimplyput.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;Also, out partner &lt;strong&gt;DSP Stylish Designs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A new brand providing unique apparel (t-shirts, hoodie, tank, crewneck,…) and other print on demand products (bottles, magnets, mouse pads,…) specifically catered to software engineering enthusiasts.​&lt;/p&gt;

&lt;p&gt;Their slogan is “𝐶𝑟𝑎𝑓𝑡𝑖𝑛𝑔 𝐸𝑙𝑒𝑔𝑎𝑛𝑐𝑒, 𝑂𝑛𝑒 𝑃𝑟𝑖𝑛𝑡 𝑎𝑡 𝑎 𝑇𝑖𝑚𝑒”.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.developmentsimplyput.com/dsp-stylish-designs" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--W5hRLPPz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fit/w_2500%2Ch_1330%2Cal_c/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" height="250" class="m-0" width="250"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.developmentsimplyput.com/dsp-stylish-designs" rel="noopener noreferrer" class="c-link"&gt;
          
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          A new brand providing unique apparel (t-shirts, hoodie, tank, crewneck,...) and other print on demand products (bottles, magnets, mouse pads,...) specifically catered to software engineers, developers, programmers, coders,... Our slogan is; Crafting Elegance, One Print at a Time.
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vch4z5LY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://static.wixstatic.com/media/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png/v1/fill/w_192%252Ch_192%252Clg_1%252Cusm_0.66_1.00_0.01/488a99_da18697d4b2740e487b6f5793e982d64%257Emv2.png" width="192" height="192"&gt;
        developmentsimplyput.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;Finally, hope you like what Development Simply Put community is offering and wish to meet you there 😃&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Use Observables with Vanilla JavaScript</title>
      <dc:creator>Ahmed Tarek Hasan</dc:creator>
      <pubDate>Fri, 31 Dec 2021 09:36:37 +0000</pubDate>
      <link>https://dev.to/ahmedtarekhasan/how-to-use-observables-with-vanilla-javascript-p6l</link>
      <guid>https://dev.to/ahmedtarekhasan/how-to-use-observables-with-vanilla-javascript-p6l</guid>
      <description>&lt;h3&gt;
  
  
  No frameworks used, just pure vanilla JavaScript.
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
While working on a side project just for fun, I wanted to write a JavaScript script to call a REST API and eventually do some cool stuff on a webpage. It is purely vanilla JavaScript, with no fancy frameworks or even libraries being used.&lt;/p&gt;

&lt;p&gt;First, I thought of using &lt;strong&gt;Promises&lt;/strong&gt; for my calls and this was easy for me. I have done that a ton of times. However, it then hit me hard — why don’t I use &lt;strong&gt;Observables?&lt;/strong&gt; I knew that vanilla JavaScript didn’t natively support Observables. But couldn’t I implement it myself? And that’s what I did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" alt="How to Use Observables with Vanilla JavaScript (JS) without any frameworks or libraries. Code Coding Programming Software Web Development" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  This is how I thought things through
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Observable itself would be of a new object type called &lt;strong&gt;Subject.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This &lt;strong&gt;Subject&lt;/strong&gt; object should expose the subscribe and next functions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;subscribe should be called by observers to subscribe to the observable stream of data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;next should be called by the &lt;strong&gt;Subject&lt;/strong&gt; owner to push/publish new data whenever available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additionally, I wanted the &lt;strong&gt;Subject&lt;/strong&gt; owner to be able to know whenever no observers were interested in its data. This would enable the &lt;strong&gt;Subject&lt;/strong&gt; owner to decide if he still wanted to get the data or not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, the &lt;strong&gt;Subject&lt;/strong&gt; owner should be able to know whenever at least one observer started being interested in its data. This would give the &lt;strong&gt;Subject&lt;/strong&gt; owner more control on its data flow and any related operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now back to the &lt;strong&gt;observer&lt;/strong&gt;. He should be able to &lt;strong&gt;unsubscribe&lt;/strong&gt; from the &lt;strong&gt;Subject&lt;/strong&gt; at any time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This leads us to a new object type called &lt;strong&gt;Subscription.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This &lt;strong&gt;Subscription&lt;/strong&gt; object should expose an unsubscribe function.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;unsubscribe should be called by the &lt;strong&gt;observer&lt;/strong&gt; whenever he wants to stop listening to the data stream coming from the &lt;strong&gt;Subject&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Following these rules, I came up with the following implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" alt="How to Use Observables with Vanilla JavaScript (JS) without any frameworks or libraries. Code Coding Programming Software Web Development" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Subscription
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsubscribeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&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="nx"&gt;unsubscribeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;unsubscribeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;self&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;Note that &lt;strong&gt;Subscription&lt;/strong&gt; just notifies the &lt;strong&gt;Subject&lt;/strong&gt; when the unsubscribe function is called.&lt;/p&gt;




&lt;h3&gt;
  
  
  Subject
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;Subject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subscribersFound&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prop&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;found&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;defineProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;subscribersCount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prop&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;count&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;unsubscribeNotificationCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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="nx"&gt;handlerId&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;handlerId&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;handlerId&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="nx"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribersFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;handlerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createGuid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;handler&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="nx"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscribersCount&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="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsubscribeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handlerId&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;handlerId&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;createGuid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;xy&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="mh"&gt;0x3&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mh"&gt;0x8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
   &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Somewhere in the Subject Owner
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscriberFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;subscriberFound&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isNowWatching&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;stopWatching&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;isNowWatching&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscriberFound&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isNowWatching&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;startWatching&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="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Subject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscribersStateChangeNotificationCallback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Somewhere in the Observer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dashboardServiceSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myDashboardService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&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="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;dashboardServiceSubscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2e2QgA1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gxbdlaqkyungajo78k87.png" alt="How to Use Observables with Vanilla JavaScript (JS) without any frameworks or libraries. Code Coding Programming Software Web Development" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s it, everything worked like a charm and I was proud of what I achieved.&lt;/p&gt;

&lt;p&gt;So, the punch line is that coding in vanilla JavaScript is not always equal to writing boring code, you can make it much more fun 😃&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Hope you found reading this story as interesting as I found writing it.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
This article was originally published &lt;a href="https://www.developmentsimplyput.com/post/how-to-use-observables-with-vanilla-javascript"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A Best Practice for Designing Interfaces in .NET C#</title>
      <dc:creator>Ahmed Tarek Hasan</dc:creator>
      <pubDate>Wed, 29 Dec 2021 10:32:12 +0000</pubDate>
      <link>https://dev.to/ahmedtarekhasan/a-best-practice-for-designing-interfaces-in-net-c-28i5</link>
      <guid>https://dev.to/ahmedtarekhasan/a-best-practice-for-designing-interfaces-in-net-c-28i5</guid>
      <description>&lt;h3&gt;
  
  
  Is it enough to define &lt;code&gt;IMyInterface&amp;lt;T&amp;gt;&lt;/code&gt;? do I need &lt;code&gt;IMyInterface&lt;/code&gt; as well?
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
While working on your masterpiece software system, you define your own interfaces to act as contracts between your different system modules and to expose some contracts to the outside world. This is not rocket science to any software developer.&lt;/p&gt;

&lt;p&gt;However, what I learned throughout my years as a Software Engineer is that we should put more care about how we design our interfaces. If you search the internet, you would find tons of resources discussing the best practices to follow when designing interfaces, some of these are actually good resources.&lt;/p&gt;

&lt;p&gt;But, I have one more best practice to tell you about which I couldn’t find online except for rare coincidences.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wU_k8xu7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2ASQ6hIAZwJcTNxcEY1EEmsg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wU_k8xu7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2ASQ6hIAZwJcTNxcEY1EEmsg.jpeg" alt="Photo by [Susan Q Yin](https://unsplash.com/@syinq?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Is it enough to define &lt;code&gt;IMyInterface&amp;lt;T&amp;gt;&lt;/code&gt;? do I need &lt;code&gt;IMyInterface&lt;/code&gt; as well?
&lt;/h2&gt;

&lt;p&gt;To answer this question, let’s walk through the example below step by step, so bear with me and don’t rush things out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PV-Tkw9q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/11358/1%2AIBfTo5s9hFUjdTk6oJth8w.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PV-Tkw9q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/11358/1%2AIBfTo5s9hFUjdTk6oJth8w.jpeg" alt="Photo by [Goh Rhy Yan](https://unsplash.com/@gohrhyyan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Disclaimer
&lt;/h3&gt;

&lt;p&gt;We would not follow a lot of the best practices here for simplicity and to drive the main focus to the topic we are discussing. So, no unnecessary abstractions, no care for immutability,….and so on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Main Entity Classes
&lt;/h3&gt;

&lt;p&gt;These are the main entity classes we are going to use.&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;// This class is representing the simple entity we are going to use&lt;/span&gt;
&lt;span class="c1"&gt;// in our example. &lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;DataId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;DataDescription&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="c1"&gt;// This class is the first kind of the parent Data class.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmployeeData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;EmployeeName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="c1"&gt;// This class is the second kind of the parent Data class.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AssetData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;AssetId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;AssetName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic Interface
&lt;/h3&gt;

&lt;p&gt;This is the generic interface we are going to use and we should focus on.&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;// This is the interface we are going to focus on.&lt;/span&gt;
&lt;span class="c1"&gt;// It is an interface for something that would be able&lt;/span&gt;
&lt;span class="c1"&gt;// to read and write data to something that is ready&lt;/span&gt;
&lt;span class="c1"&gt;// to be used this way.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We notice on this interface the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It is a generic interface which accepts a generic parameter of type &lt;code&gt;Data&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It has an Initialize method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It has a &lt;code&gt;Read(int dataId)&lt;/code&gt; method which expects an integer parameter and returns a &lt;code&gt;TData&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It has &lt;code&gt;Write(TData data)&lt;/code&gt; method which expects a &lt;code&gt;TData&lt;/code&gt; parameter.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generic Interface Implementer
&lt;/h3&gt;

&lt;p&gt;This is the class implementing our generic interface. The class itself is generic.&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;// This is the class implementing our IReaderWriter&amp;lt;TData&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// but now we know that it is going to save and retrieve&lt;/span&gt;
&lt;span class="c1"&gt;// data to and from a file. We would not care about the&lt;/span&gt;
&lt;span class="c1"&gt;// implementation so don't give it too much thought.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&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;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We notice on this class the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It is a generic class.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The methods are throwing exceptions and this is intentionally done to drive the main focus to where it belongs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inside the Employee Module
&lt;/h3&gt;

&lt;p&gt;Now, in your system, you have a module dedicated to managing &lt;strong&gt;Employee&lt;/strong&gt; data, let’s call this module; &lt;strong&gt;Employee Module&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;Employee Module&lt;/strong&gt;, you are sure of the type of the data you are dealing with, it is obviously of type &lt;code&gt;EmployeeData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s why you can write code like the one below without having any problems.&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;employeeDataFileReaderWriter&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;FileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;EmployeeData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;employeeDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;employeeDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&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;EmployeeData&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;DataId&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="n"&gt;DataDescription&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some description."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EmployeeName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Ahmed"&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;ahmed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;employeeDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inside the Asset Module
&lt;/h3&gt;

&lt;p&gt;Now, in your system, you have a module dedicated to managing &lt;strong&gt;Asset&lt;/strong&gt; data, let’s call this module; &lt;strong&gt;Asset Module&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inside the &lt;strong&gt;Asset Module&lt;/strong&gt;, you are sure of the type of the data you are dealing with, it is obviously of type &lt;code&gt;AssetData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That’s why you can write code like the one below without having any problems.&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;assetDataFileReaderWriter&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;FileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AssetData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;assetDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;assetDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&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;AssetData&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;DataId&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="n"&gt;DataDescription&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Some description."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AssetId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AssetName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Asset 5."&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;asset5&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assetDataFileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What About a Common Module
&lt;/h3&gt;

&lt;p&gt;Now let’s assume that you have a common module that has a &lt;code&gt;Run(IReaderWriter readerWriter)&lt;/code&gt; method. Inside this method you want to call the &lt;code&gt;Initialize&lt;/code&gt; method of the passed in &lt;code&gt;readerWriter&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;You would try to write something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K-md3w1k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANO9BgF8GPnjUC-LQNDi08g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K-md3w1k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ANO9BgF8GPnjUC-LQNDi08g.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="466" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is clear now that you can’t do it as you don’t have a non-generic definition of the &lt;code&gt;IReaderWriter&lt;/code&gt; interface. In other words, we only have &lt;code&gt;IReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt;, not &lt;code&gt;IReaderWriter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u84Qxats--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2Ai3BDvzg5_VxUFhFWTAbnYg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u84Qxats--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2Ai3BDvzg5_VxUFhFWTAbnYg.jpeg" alt="Photo by [Brett Jordan](https://unsplash.com/@brett_jordan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrong Expectations
&lt;/h3&gt;

&lt;p&gt;Now, I can hear someone shouting from a far distance saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Huh, it is a piece of cake. Let’s use &lt;code&gt;IReaderWriter&amp;lt;object&amp;gt;&lt;/code&gt;. Every class is a child of Object, right?….. genius.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My answer to him is that he should do his homework as this is not going to work. If either you or him don’t trust me on this, just give it a try and you would see the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cgLfObyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AuFS0BJERZdJJU7vdL02oCg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cgLfObyB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AuFS0BJERZdJJU7vdL02oCg.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="535" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need more explanation right, the short answer is because your interface is &lt;strong&gt;Invariant;&lt;/strong&gt; you can’t call a method expecting &lt;code&gt;IReaderWriter&amp;lt;SomeClass&amp;gt;&lt;/code&gt; and pass in an instance of &lt;code&gt;IReaderWriter&amp;lt;AnyOtherClass&amp;gt;&lt;/code&gt;. The only acceptable call would be with passing &lt;code&gt;IReaderWriter&amp;lt;SomeClass&amp;gt;&lt;/code&gt;, nothing else.&lt;/p&gt;

&lt;p&gt;If you want to understand more you can check my story &lt;a href="https://dev.to/ahmedtarekhasan/covariance-and-contravariance-in-net-c-20nl"&gt;Covariance and Contravariance in .NET C#. Have hard time understanding it? Let me simplify it for you.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4sgZeZBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2Ap1ea1_zCuEYSs0cfY3S-Ig.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4sgZeZBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2Ap1ea1_zCuEYSs0cfY3S-Ig.jpeg" alt="Photo by [Brett Jordan](https://unsplash.com/@brett_jordan?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  This Is the Way
&lt;/h3&gt;

&lt;p&gt;Now you understand why we need to define a non-generic &lt;code&gt;IReaderWriter&lt;/code&gt; interface.&lt;/p&gt;

&lt;p&gt;Therefore, moving on to the implementation, we can end up with this code:&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&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;IReaderWriter&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can notice the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We defined a new interface but this time it is a non-generic interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This interface would define only the &lt;code&gt;Initialize()&lt;/code&gt; method as this is what we actually need in the common module or even the new ones if they come in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now the other generic interface can safely extend the non-generic one with the &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt; methods without changing anything on the signature.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s Give It a Test Drive
&lt;/h3&gt;

&lt;p&gt;So, now let’s go back to our common module and see if it is going to work or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VFwFubQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AdR4BCI8sXZUzPSTOijQGag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VFwFubQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AdR4BCI8sXZUzPSTOijQGag.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="459" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, it is working. Let’s celebrate and get something to eat and drink, what a trip 🙂&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I don’t want to be a bearer of bad news here, but, I have bad news…&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I61ehW4h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10008/1%2AkNiQOJ1bd-qSEYpzj4-ynw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I61ehW4h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10008/1%2AkNiQOJ1bd-qSEYpzj4-ynw.jpeg" alt="Photo by [Nik Shuliahin](https://unsplash.com/@tjump?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why So Sad
&lt;/h3&gt;

&lt;p&gt;You have &lt;strong&gt;new requirements&lt;/strong&gt; coming in and the common module needs some modifications. The common module now should be able to &lt;strong&gt;store and retrieve data in and from a Blob storage&lt;/strong&gt;. The Blob storage can store any kind of data.&lt;/p&gt;

&lt;p&gt;So, based on this input, you would try to do something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KeZnMRCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2cG2du_xg3uyuzPxSqBcOQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KeZnMRCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2cG2du_xg3uyuzPxSqBcOQ.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="720" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is clear now that it is not going to work as &lt;code&gt;IReaderWriter&lt;/code&gt; interface doesn’t define the &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt; methods. They are defined in the &lt;code&gt;IReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt;. However, on the common module and at the moment of calling &lt;code&gt;StoreInBlob&lt;/code&gt; and &lt;code&gt;RetrieveFromBlob&lt;/code&gt; methods, we don’t know the type of data. So, what to do!!!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xwzcqu54--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/9792/1%2AcjoTe1ydGwUA0i0ULI4tLw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xwzcqu54--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/9792/1%2AcjoTe1ydGwUA0i0ULI4tLw.jpeg" alt="Photo by [NeONBRAND](https://unsplash.com/@neonbrand?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Wrong Way To Go
&lt;/h3&gt;

&lt;p&gt;You might now lose hope and sadly decide to drop the whole generic interface thing. You would change the code to the following:&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileReaderWriter&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, now the common module would be fine as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z7Ff4r7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AtxWiRigg1sGii5SqADQhKg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z7Ff4r7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AtxWiRigg1sGii5SqADQhKg.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="723" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, you lost the edge of dealing with strong-typed objects as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7khzQbwL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AV9D_z1fieSgqLvGUPriRFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7khzQbwL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AV9D_z1fieSgqLvGUPriRFQ.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="762" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have to cast your &lt;strong&gt;Employee&lt;/strong&gt; object so that you can access its unique members, like &lt;code&gt;EmployeeName&lt;/code&gt; as in the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7Z-107hh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AEgRCXGc4is8capm9_McvSQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7Z-107hh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AEgRCXGc4is8capm9_McvSQ.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, you have to cast your **Asset **object so that you can access its unique members, like &lt;code&gt;AssetName&lt;/code&gt; as in the image.&lt;/p&gt;

&lt;p&gt;So, now what????&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y7DopZpY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/14720/1%2AAXhwXXSNN1Cr9Ca_AbXeIw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y7DopZpY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/14720/1%2AAXhwXXSNN1Cr9Ca_AbXeIw.jpeg" alt="Photo by [Michael Carruth](https://unsplash.com/@michaelcarruth?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Moment of Truth
&lt;/h3&gt;

&lt;p&gt;The keyword for the best solution here is the word &lt;code&gt;new&lt;/code&gt;. Let me break it down for you.&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&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;IReaderWriter&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can notice the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;IReaderWriter&lt;/code&gt; interface now defines are the required methods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, for the &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt; methods, they are now using the parent &lt;code&gt;Data&lt;/code&gt; entity type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;IReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt; interface now extends the &lt;code&gt;IReaderWriter&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This means that it also indirectly defines the three methods we know about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, inside the &lt;code&gt;IReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt; interface, we need to use the generic type &lt;code&gt;TData&lt;/code&gt;, not the parent &lt;code&gt;Data&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To do so, we need to add &lt;code&gt;TData Read(int dataId);&lt;/code&gt; and &lt;code&gt;void Write(TData data);&lt;/code&gt; methods to the &lt;code&gt;IReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the read method, you can’t do this because the parent interface, the non-generic one, already defines the same exact method in terms of name and input parameters, but only different return type.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This would confuse the compiler at run time as it would not know which method to call, the one returning &lt;code&gt;Data&lt;/code&gt; or the other one returning &lt;code&gt;TData&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That’s why the compiler would not allow you to do so unless you add the &lt;code&gt;new&lt;/code&gt; keyword at the start of the method definition as in the code above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This instructs the compiler to hide the &lt;code&gt;Read&lt;/code&gt; method inherited from the parent and replace it with the one defined after the &lt;code&gt;new&lt;/code&gt; keyword.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, you might ask, why didn’t we do the same with the &lt;code&gt;Write&lt;/code&gt; method?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The answer is simply because we don’t need to do so. In the parent interface, we already have a method called &lt;code&gt;Write&lt;/code&gt; which expects a parameter of type &lt;code&gt;Data&lt;/code&gt; which is the parent of all types that could be passed in to the &lt;code&gt;Write&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This means that this method could be called passing any &lt;code&gt;TData&lt;/code&gt; could come.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Another thing, if you try to use the &lt;code&gt;new&lt;/code&gt; keyword with the &lt;code&gt;Write&lt;/code&gt; method, you would get a warning that you are actually not hiding anything from the parent interface. This is logical as the two &lt;code&gt;Write&lt;/code&gt; methods have different input parameter types, so, it is sound and clear to the compiler that they are two different methods.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;class&lt;/span&gt; &lt;span class="nc"&gt;FileReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&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;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="nf"&gt;Read&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;dataId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;dataId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;TData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can notice the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The old three methods are the same.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now we have two more methods implemented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first method is &lt;code&gt;Data IReaderWriter.Read(int dataId) { return Read(dataId); }&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This method is an &lt;strong&gt;explicit implementation&lt;/strong&gt; of the &lt;code&gt;Data Read(int dataId);&lt;/code&gt; method defined in the parent &lt;code&gt;IReaderWriter&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This means that whenever an object of the &lt;code&gt;FileReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt; class is casted, implicitly or explicitly, as the non-generic interface &lt;code&gt;IReaderWriter&lt;/code&gt;, this &lt;code&gt;Read&lt;/code&gt; method implementation would be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The second method is &lt;code&gt;void IReaderWriter.Write(Data data) { Write((TData)data); }&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This method is an &lt;strong&gt;explicit implementation&lt;/strong&gt; of the &lt;code&gt;void Write(Data data);&lt;/code&gt; method defined in the parent &lt;code&gt;IReaderWriter&lt;/code&gt; interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This means that whenever an object of the &lt;code&gt;FileReaderWriter&amp;lt;TData&amp;gt;&lt;/code&gt; class is casted, implicitly or explicitly, as the non-generic interface &lt;code&gt;IReaderWriter&lt;/code&gt;, this &lt;code&gt;Write&lt;/code&gt; method implementation would be used.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This now leads to the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7dMQZBQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AiUjkPAgr655LVhWt1R-uZg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7dMQZBQS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AiUjkPAgr655LVhWt1R-uZg.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p48ZkmlM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2An3cVGfL6TEDZ73OrLUXlsQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p48ZkmlM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2An3cVGfL6TEDZ73OrLUXlsQ.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="723" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, everything is working as it should 🙂&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ISHBnnY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/6064/1%2AWqEtbutQR9C4vWMYD7KMPQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ISHBnnY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/6064/1%2AWqEtbutQR9C4vWMYD7KMPQ.jpeg" alt="Photo by [Nick Fewings](https://unsplash.com/@jannerboy62?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It Is What It Is
&lt;/h3&gt;

&lt;p&gt;This design technique -afraid of even calling it a pattern- is already used in .NET classes you are using daily. Did you notice that in .NET we have &lt;code&gt;IEnumerable&lt;/code&gt; and &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;? Could you imagine if we don’t have &lt;code&gt;IEnumerable&lt;/code&gt; what would life be 🙂&lt;/p&gt;

&lt;p&gt;This would mean that you can’t write code which loops on an enumerable, just an enumerable. You would always need to know first the type of items inside the enumerable.&lt;/p&gt;

&lt;p&gt;You can argue that you still can write a method which accepts &lt;code&gt;&amp;lt;T&amp;gt;&lt;/code&gt; and then it would pass it to the &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;, but my friend, this would keep bubbling up till you eventually would have to choose an entity type. This entity type is not always defined on all layers or levels of code as we proved above.&lt;/p&gt;

&lt;p&gt;Therefore, my final advice to you, don’t try to beat around the bushes, it is what it is…&lt;br&gt;
&lt;br&gt;&lt;br&gt;
That’s it, hope you found reading this story as interesting as I found writing it.&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
This article was originally published &lt;a href="https://www.developmentsimplyput.com/post/a-best-practice-for-designing-interfaces-in-net-c"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YOYG2Ene--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22vftqh632cvcqkmbzhd.png" alt="A Best Practice for Designing Interfaces in DotNet (.NET) CSharp (C#). When to define a non-generic interface in addition to the generic interface" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;These are resources you might find useful.&lt;br&gt;
&lt;a href="https://dev.to/ahmedtarekhasan/covariance-and-contravariance-in-net-c-20nl"&gt;Covariance and Contravariance in .NET C#&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>architecture</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
    <item>
      <title>Covariance and Contravariance in .NET C#</title>
      <dc:creator>Ahmed Tarek Hasan</dc:creator>
      <pubDate>Mon, 27 Dec 2021 22:08:34 +0000</pubDate>
      <link>https://dev.to/ahmedtarekhasan/covariance-and-contravariance-in-net-c-20nl</link>
      <guid>https://dev.to/ahmedtarekhasan/covariance-and-contravariance-in-net-c-20nl</guid>
      <description>&lt;h3&gt;
  
  
  Have hard time understanding it? Let me simplify it for you.
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
If it is so hard on you to understand what &lt;strong&gt;Covariance&lt;/strong&gt; and &lt;strong&gt;Contravariance&lt;/strong&gt; in &lt;strong&gt;.NET C#&lt;/strong&gt; means, don’t feel ashamed of it, you are not alone.&lt;/p&gt;

&lt;p&gt;It happened to me and many other developers. I even know experienced developers who either don’t know about them and are using them but still can’t understand them well enough.&lt;/p&gt;

&lt;p&gt;From where I see it, this is happening because every time I come across an article talking about &lt;strong&gt;Covariance&lt;/strong&gt; and &lt;strong&gt;Contravariance&lt;/strong&gt;, I find it focused on some technical terminologies rather than being concerned about the reason why we have them in the first place and what we would have missed if they didn’t exist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Jn3O7Bcl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8064/1%2A09u_9YpDdTA_SyZHFQYMaQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Jn3O7Bcl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8064/1%2A09u_9YpDdTA_SyZHFQYMaQ.jpeg" alt="Photo by [Tadas Sar](https://unsplash.com/@stadsa?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Microsoft’s Definition
&lt;/h2&gt;

&lt;p&gt;If you check &lt;a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/"&gt;Microsoft’s documentation&lt;/a&gt; for the &lt;strong&gt;Covariance&lt;/strong&gt; and &lt;strong&gt;Contravariance&lt;/strong&gt; in &lt;strong&gt;.NET C#&lt;/strong&gt;, you would find this definition:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In C#, covariance and contravariance enable implicit reference conversion for array types, delegate types, and generic type arguments. Covariance preserves assignment compatibility and contravariance reverses it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Do you get it? do you like it?&lt;/p&gt;

&lt;p&gt;You can search the internet and you will find tons of resources about this topic. You will come across definitions, history, when introduced, code samples,… and many others and this is not what you would find in this story. I promise you that what you would see here is different….&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vvUBFeDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7750/1%2AKwMyZMxmrJFFAVwP6fBpZQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vvUBFeDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7750/1%2AKwMyZMxmrJFFAVwP6fBpZQ.jpeg" alt="Photo by [Rhys Kentish](https://unsplash.com/@rhyskentish?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What are they actually?
&lt;/h2&gt;

&lt;p&gt;Basically, what Microsoft did is that they added a small addition to the way you define your generic template type place holder, the famous &lt;em&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What you used to do when defining a generic interface is to follow the pattern public interface &lt;code&gt;IMyInterface&amp;lt;T&amp;gt; {…}&lt;/code&gt;. After having Covariance and Contravariance introduced, you can now follow the pattern public interface &lt;code&gt;IMyInterface&amp;lt;out T&amp;gt; {…}&lt;/code&gt; or public interface &lt;code&gt;IMyInterface&amp;lt;in T&amp;gt; {…}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do you recognize the extra &lt;strong&gt;out&lt;/strong&gt; and &lt;strong&gt;in&lt;/strong&gt;?&lt;br&gt;
Have you seen them somewhere else?&lt;br&gt;
May be on the famous .NET public interface &lt;code&gt;IEnumerable&amp;lt;out T&amp;gt;&lt;/code&gt;?&lt;br&gt;
or the famous .NET public interface &lt;code&gt;IComparable&amp;lt;in T&amp;gt;&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Microsoft introduced a new concept so that the compiler -at design time- would make sure that the types of objects you use and pass around generic members would not throw runtime exceptions caused by wrong type expectations.&lt;/p&gt;

&lt;p&gt;Still not clear, right? Just bear with me... Let’s assume that the compiler doesn’t apply any design time restrictions and see what would happen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ygiLxcGo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8000/1%2AyQ9Uk-RgSLzXhgXABBK2tA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ygiLxcGo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8000/1%2AyQ9Uk-RgSLzXhgXABBK2tA.jpeg" alt="Photo by [Rick Monteiro](https://unsplash.com/@rickmontii?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What if the compiler doesn’t apply any design time restrictions?
&lt;/h2&gt;

&lt;p&gt;To be able to work on an appropriate example, let’s define the following:&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;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F1&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F2&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F3&lt;/span&gt;&lt;span class="p"&gt;(){}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;public&lt;/span&gt; &lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking into the code above, you will notice that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Class A has &lt;code&gt;F1()&lt;/code&gt; defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Class B has &lt;code&gt;F1()&lt;/code&gt; and &lt;code&gt;F2()&lt;/code&gt; defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Class C has &lt;code&gt;F1()&lt;/code&gt;, &lt;code&gt;F2()&lt;/code&gt; , and &lt;code&gt;F3()&lt;/code&gt; defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The interface &lt;code&gt;IReaderWriter&lt;/code&gt; has &lt;code&gt;Read()&lt;/code&gt; which returns an object of type &lt;code&gt;TEntity&lt;/code&gt; and &lt;code&gt;Write(TEntity entity)&lt;/code&gt; which expects a parameter of type &lt;code&gt;TEntity&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then let’s define a &lt;code&gt;TestReadWriter()&lt;/code&gt; method as follows:&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;TestReaderWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;param&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;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Calling TestReadWriter() when passing in an instance of IReaderWriter&lt;b&gt;
&lt;/b&gt;
&lt;/h3&gt;

&lt;p&gt;This should &lt;strong&gt;work fine&lt;/strong&gt; as we are not violating any rules. &lt;code&gt;TestReadWriter()&lt;/code&gt; is already expecting a parameter of type &lt;code&gt;IReaderWriter&amp;lt;B&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling &lt;code&gt;TestReadWriter()&lt;/code&gt; when passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Keeping in mind the assumption that the compiler doesn’t apply any design time restrictions&lt;/em&gt;, this means that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;param.Read()&lt;/code&gt; would return an instance of class &lt;strong&gt;A&lt;/strong&gt;, &lt;strong&gt;not B&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;=&amp;gt;&lt;/strong&gt; So, the &lt;code&gt;var b&lt;/code&gt; would actually be of type &lt;strong&gt;A&lt;/strong&gt;, &lt;strong&gt;not B&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;=&amp;gt;&lt;/strong&gt; This would lead to the &lt;code&gt;b.F2()&lt;/code&gt; line to &lt;strong&gt;fail&lt;/strong&gt; as the &lt;code&gt;var b&lt;/code&gt; -which is actually of type &lt;strong&gt;A&lt;/strong&gt;- does not have &lt;code&gt;F2()&lt;/code&gt; defined&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;param.Write()&lt;/code&gt; line in the code above would be expecting to receive a parameter of type &lt;strong&gt;A&lt;/strong&gt;, not &lt;strong&gt;B&lt;/strong&gt;&lt;br&gt;
=&amp;gt; So, calling &lt;code&gt;param.Write()&lt;/code&gt; while passing in a parameter of type &lt;strong&gt;B&lt;/strong&gt; would both &lt;strong&gt;work fine&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, since in the point &lt;strong&gt;#1&lt;/strong&gt; we are expecting a runtime failure, then we can’t call &lt;code&gt;TestReadWriter()&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calling &lt;code&gt;TestReadWriter()&lt;/code&gt; when passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Keeping in mind the assumption that the compiler doesn’t apply any design time restrictions&lt;/em&gt;, this means that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;param.Read()&lt;/code&gt; would return an instance of class &lt;strong&gt;C&lt;/strong&gt;, not &lt;strong&gt;B&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;=&amp;gt;&lt;/strong&gt; So, the &lt;code&gt;var b&lt;/code&gt; would actually be of type &lt;strong&gt;C&lt;/strong&gt;, not &lt;strong&gt;B&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;=&amp;gt;&lt;/strong&gt; This would lead to the &lt;code&gt;b.F2()&lt;/code&gt; line to &lt;strong&gt;work fine&lt;/strong&gt; as the &lt;code&gt;var b&lt;/code&gt; would have &lt;code&gt;F2()&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;param.Write()&lt;/code&gt; line in the code above would be expecting to receive a parameter of type &lt;strong&gt;C&lt;/strong&gt;, not &lt;strong&gt;B&lt;/strong&gt;&lt;br&gt;
=&amp;gt; So, calling &lt;code&gt;param.Write()&lt;/code&gt; while passing in a parameter of type &lt;strong&gt;B&lt;/strong&gt; would &lt;strong&gt;fail&lt;/strong&gt; because simply you can’t replace &lt;strong&gt;C&lt;/strong&gt; with its parent &lt;strong&gt;B&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, since in the point &lt;strong&gt;#2&lt;/strong&gt; we are expecting a runtime failure, then we can’t call &lt;code&gt;TestReadWriter()&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HRlxuzMZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7998/1%2AHxHoLEPKokFwd0_NMVnXUQ.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HRlxuzMZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/7998/1%2AHxHoLEPKokFwd0_NMVnXUQ.jpeg" alt="Photo by [Markus Winkler](https://unsplash.com/@markuswinkler?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s analyze what we have discovered up to this moment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; when passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;B&amp;gt;&lt;/code&gt; is always fine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; when passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt; would be fine if we don’t have the &lt;code&gt;param.Read()&lt;/code&gt; call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; when passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt; would be fine if we don’t have the &lt;code&gt;param.Write()&lt;/code&gt; call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;However, since we always have a mix between &lt;code&gt;param.Read()&lt;/code&gt; and &lt;code&gt;param.Write()&lt;/code&gt;, we would always have to stick to calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;B&amp;gt;&lt;/code&gt;, nothing else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unless…….&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jZ9bV2JD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2AcIalJUmZN88XP3ZQZXBCBw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jZ9bV2JD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/10368/1%2AcIalJUmZN88XP3ZQZXBCBw.jpeg" alt="Photo by [Hal Gatewood](https://unsplash.com/@halacious?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alternative
&lt;/h2&gt;

&lt;p&gt;What if we make sure that the &lt;code&gt;IReaderWriter&amp;lt;TEntity&amp;gt;&lt;/code&gt; interface defines either &lt;code&gt;TEntity Read()&lt;/code&gt; or &lt;code&gt;void Write(TEntity entity)&lt;/code&gt;, not both of them at the same time.&lt;/p&gt;

&lt;p&gt;Therefore, if we drop the &lt;code&gt;TEntity Read()&lt;/code&gt;, we would be able to call &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt; or &lt;code&gt;IReaderWriter&amp;lt;B&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, if we drop the &lt;code&gt;void Write(TEntity entity)&lt;/code&gt;, we would be able to call &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;B&amp;gt;&lt;/code&gt; or &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This would be better for us as it would be less restrictive, right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ukFJcqyW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8576/1%2An1N2ihMRmi_XX4st_Mz2xw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ukFJcqyW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/8576/1%2An1N2ihMRmi_XX4st_Mz2xw.jpeg" alt="Photo by [Agence Olloweb](https://unsplash.com/@olloweb?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText)" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Time for some Facts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the real world, the compiler -in design time- would never allow calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt;. You would get a compilation error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, the compiler -in design time- would not allow calling &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt;. You would get a compilation error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From point #1 and #2, this is called &lt;strong&gt;Invariance&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if you drop the &lt;code&gt;TEntity Read()&lt;/code&gt; from the &lt;code&gt;IReaderWriter&amp;lt;TEntity&amp;gt;&lt;/code&gt; interface, the compiler -in design time- would not allow you to call &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;A&amp;gt;&lt;/code&gt;. You would get a compilation error. This is because the compiler would not -implicitly by itself- look into the members defined into the interface and see if it is going to always work at runtime or not. You will need to do this by yourself through &lt;code&gt;&amp;lt;in TEntity&amp;gt;&lt;/code&gt;. This acts as a promise from you to the compiler that all members in the interface would either don’t depend on &lt;code&gt;TEntity&lt;/code&gt; or deal with it as an &lt;strong&gt;input&lt;/strong&gt;, &lt;strong&gt;not an output&lt;/strong&gt;. This is called &lt;strong&gt;Contravariance&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Similarly, even if you drop the void &lt;code&gt;Write(TEntity entity)&lt;/code&gt; from the &lt;code&gt;IReaderWriter&amp;lt;TEntity&amp;gt;&lt;/code&gt; interface, the compiler -in design time- would not allow you to call &lt;code&gt;TestReadWriter(IReaderWriter&amp;lt;B&amp;gt; param)&lt;/code&gt; with passing in an instance of &lt;code&gt;IReaderWriter&amp;lt;C&amp;gt;&lt;/code&gt;. You would get a compilation error. This is because the compiler would not -implicitly by itself- look into the members defined into the interface and see if it is going to always work at runtime or not. You will need to do this by yourself through &lt;code&gt;&amp;lt;out TEntity&amp;gt;&lt;/code&gt;. This acts as a promise from you to the compiler that all members in the interface would either don’t depend on &lt;code&gt;TEntity&lt;/code&gt; or deal with it as an &lt;strong&gt;output&lt;/strong&gt;, &lt;strong&gt;not an input&lt;/strong&gt;. This is called &lt;strong&gt;Covariance&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Therefore, adding &lt;code&gt;&amp;lt;out &amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;in &amp;gt;&lt;/code&gt; makes the compiler less restrictive to serve our needs, not more restrictive as some developers would think.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zh3BLdDC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v7ax1qow4hg7ctlv8wyq.png" alt="Simple explanation of DotNet (.NET) C# Invariance, Covariance &amp;amp; Contravariance Cheat Sheet  CSharp Programming Software Development Best Practice" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lTHCvPvI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2ACBrnK4hi6OItpSE6CWctzA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lTHCvPvI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3840/1%2ACBrnK4hi6OItpSE6CWctzA.jpeg" alt="Image by [Harish Sharma](https://pixabay.com/users/harishs-3407954/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=3245793) from [Pixabay](https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=3245793)" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;At this point, you should already understand the full story of &lt;strong&gt;Invariance&lt;/strong&gt;, &lt;strong&gt;Covariance&lt;/strong&gt; and &lt;strong&gt;Contravariance&lt;/strong&gt;. However, as a quick recap, you can deal with the following as a &lt;strong&gt;cheat sheet&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Mix between input and output generic type =&amp;gt; Invariance =&amp;gt; the most restrictive =&amp;gt; can’t replace with parents or children.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added &lt;code&gt;&amp;lt;in &amp;gt;&lt;/code&gt; =&amp;gt; only &lt;strong&gt;input&lt;/strong&gt; =&amp;gt; &lt;strong&gt;Contravariance&lt;/strong&gt; =&amp;gt; &lt;strong&gt;itself or replace with parents&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added &lt;code&gt;&amp;lt;out &amp;gt;&lt;/code&gt; =&amp;gt; only &lt;strong&gt;output&lt;/strong&gt; =&amp;gt; &lt;strong&gt;Covariance&lt;/strong&gt; =&amp;gt; &lt;strong&gt;itself or replace with children&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Cx60GAD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2058/1%2A85tBjg8Kkt-54vhvVr8tNQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Cx60GAD2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2058/1%2A85tBjg8Kkt-54vhvVr8tNQ.png" alt="Image by [Ahmed Tarek](https://medium.com/@eng_ahmed.tarek)" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I will drop here some code for you to check. It would help you practice more.&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;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Linq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;DotNetVariance&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&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;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerA&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;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerB&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;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerC&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;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;writerA&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;Writer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;writerB&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;Writer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;writerC&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;Writer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerWriterA&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;ReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerWriterB&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;ReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
            &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;readerWriterC&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;ReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Covariance&lt;/span&gt;
            &lt;span class="c1"&gt;// IReader&amp;lt;TEntity&amp;gt; is Covariant, this means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. All members either don't deal with TEntity or have it in the return type, not the input parameters&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. In a call, IReader&amp;lt;TEntity&amp;gt; could be replaced by any IReader&amp;lt;TAnotherEntity&amp;gt; given that TAnotherEntity&lt;/span&gt;
            &lt;span class="c1"&gt;// is a child -directly or indirectly- of TEntity&lt;/span&gt;

            &lt;span class="c1"&gt;// TestReader(readerB) is ok because TestReader is already expecting IReader&amp;lt;B&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;TestReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// TestReader(readerC) is ok because C is a child of B&lt;/span&gt;
            &lt;span class="nf"&gt;TestReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// TestReader(readerA) is NOT ok because A is a not a child of B&lt;/span&gt;
            &lt;span class="nf"&gt;TestReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;

            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Contravariance&lt;/span&gt;
            &lt;span class="c1"&gt;// IWriter&amp;lt;TEntity&amp;gt; is Contravariant, this means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. All members either don't deal with TEntity or have it in the input parameters, not in the return type&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. In a call, IWriter&amp;lt;TEntity&amp;gt; could be replaced by any IWriter&amp;lt;TAnotherEntity&amp;gt; given that TAnotherEntity&lt;/span&gt;
            &lt;span class="c1"&gt;// is a parent -directly or indirectly- of TEntity&lt;/span&gt;

            &lt;span class="c1"&gt;// TestWriter(writerB) is ok because TestWriter is already expecting IWriter&amp;lt;B&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;TestWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writerB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// TestWriter(writerA) is ok because A is a parent of B&lt;/span&gt;
            &lt;span class="nf"&gt;TestWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writerA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// TestWriter(writerC) is NOT ok because C is a not a parent of B&lt;/span&gt;
            &lt;span class="nf"&gt;TestWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;writerC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;

            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Invariance&lt;/span&gt;
            &lt;span class="c1"&gt;// IReaderWriter&amp;lt;TEntity&amp;gt; is Invariant, this means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. Some members have TEntity in the input parameters and others have TEntity in the return type&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. In a call, IReaderWriter&amp;lt;TEntity&amp;gt; could not be replaced by any IReaderWriter&amp;lt;TAnotherEntity&amp;gt;&lt;/span&gt;

            &lt;span class="c1"&gt;// IReaderWriter(readerWriterB) is ok because TestReaderWriter is already expecting IReaderWriter&amp;lt;B&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;TestReaderWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerWriterB&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// IReaderWriter(readerWriterA) is NOT ok because IReaderWriter&amp;lt;B&amp;gt; can not be replaced by IReaderWriter&amp;lt;A&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;TestReaderWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerWriterA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// IReaderWriter(readerWriterC) is NOT ok because IReaderWriter&amp;lt;B&amp;gt; can not be replaced by IReaderWriter&amp;lt;C&amp;gt;&lt;/span&gt;
            &lt;span class="nf"&gt;TestReaderWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;readerWriterC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;param&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;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestReader with a param of type IReader&amp;lt;A&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// param.Read() would return an instance of class A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, the var b would actually be of type A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; This would lead to the b.F2() line in the code above to fail as the var b doesn't have F2()&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestReader with a param of type IReader&amp;lt;C&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// param.Read() would return an instance of class C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, the var b would actually be of type C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; This would lead to the b.F2() line in the code above to work fine as the var b would have F2()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;param&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;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;B&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestWriter with a param of type IWriter&amp;lt;A&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// param.Write() line in the code above would be expecting to receive a parameter of type A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, calling param.Write() while passing in a parameter of type A or B would both work&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestWriter with a param of type IWriter&amp;lt;C&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// param.Write() line in the code above would be expecting to receive a parameter of type C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, calling param.Write() while passing in a parameter of type B would not work&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestReaderWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;param&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;b&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;F2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestReaderWriter with a param of type IReaderWriter&amp;lt;A&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. param.Read() would return an instance of class A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, the var b would actually be of type A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; This would lead to the b.F2() line in the code above to fail as the var b doesn't have F2()&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. param.Write() line in the code above would be expecting to receive a parameter of type A, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, calling param.Write() while passing in a parameter of type A or B would both work&lt;/span&gt;

            &lt;span class="c1"&gt;// What if the compiler allows calling TestReaderWriter with a param of type IReaderWriter&amp;lt;C&amp;gt;, This means that:&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. param.Read() would return an instance of class C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, the var b would actually be of type C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; This would lead to the b.F2() line in the code above to work fine as the var b would have F2()&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. param.Write() line in the code above would be expecting to receive a parameter of type C, not B&lt;/span&gt;
            &lt;span class="c1"&gt;//      =&amp;gt; So, calling param.Write() while passing in a parameter of type B would not work&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Hierarchy&lt;/span&gt; &lt;span class="n"&gt;Classes&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F1&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F2&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;B&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;F3&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Covariant&lt;/span&gt; &lt;span class="n"&gt;IReader&lt;/span&gt;
    &lt;span class="c1"&gt;// IReader&amp;lt;TEntity&amp;gt; is Covariant as all members either don't deal with TEntity or have it in the return type&lt;/span&gt;
    &lt;span class="c1"&gt;// not the input parameters&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;IReader&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;public&lt;/span&gt; &lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TEntity&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="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Contravariant&lt;/span&gt; &lt;span class="n"&gt;IWriter&lt;/span&gt;
    &lt;span class="c1"&gt;// IWriter&amp;lt;TEntity&amp;gt; is Contravariant as all members either don't deal with TEntity or have it in the input parameters&lt;/span&gt;
    &lt;span class="c1"&gt;// not the return type&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;IWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;

    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;region&lt;/span&gt; &lt;span class="n"&gt;Invariant&lt;/span&gt; &lt;span class="n"&gt;IReaderWriter&lt;/span&gt;
    &lt;span class="c1"&gt;// IReaderWriter&amp;lt;TEntity&amp;gt; is Invariant as some members have TEntity in the input parameters&lt;/span&gt;
    &lt;span class="c1"&gt;// and others have TEntity in the return type&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&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;IReaderWriter&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TEntity&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;public&lt;/span&gt; &lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="nf"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="n"&gt;endregion&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
That’s it, hope you found reading this story as interesting as I found writing it.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
This article was originally published &lt;a href="https://www.developmentsimplyput.com/post/variance-invariance-covariance-contravariance-dotnet"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
