CINXE.COM
Revisiting SOLID principles | DotNetCurry
<!DOCTYPE html> <html lang="en"> <head id="ctl00_Head1"><meta charset="utf-8" /><title> Revisiting SOLID principles | DotNetCurry </title><meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" /><meta name="description" content="This tutorial summarizes SOLID principles and answers some questions our viewers have asked about SOLID." /><meta name="keywords" content="Software Gardening" /><meta name="author" content="DotNetCurry.com" /><meta name="CCBot" content="nofollow" /><link rel="shortcut icon" href="../../img/favicon.ico" /><link rel="icon" type="image/ico" href="../../img/favicon.ico" /><link rel="stylesheet" href="../../js/font-awesome/css/font-awesome.min.css" /><link rel="canonical" href="https://www.dotnetcurry.com/software-gardening/1365/solid-principles" /><link href="/content/site?v=dSwaMsW0iplPE-tk0JGVwhcZRf6VKKqSg-lTdPGvZso1" rel="stylesheet"/> <style>.async-hide { opacity: 0 !important} </style> <!-- GA disabled 17062020 --> <!--<script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date; h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')}; (a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c; })(window,document.documentElement,'async-hide','dataLayer',4000, {'GTM-NJXQ5BG':true});</script> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-2417460-4', 'auto'); ga('require', 'GTM-NJXQ5BG'); ga('send', 'pageview'); </script>--> <!-- Facebook Pixel Code --> <script> !function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n; n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '1902706389940870', { //em: 'insert_email_variable' }); fbq('track', 'PageView'); </script> <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1902706389940870&ev=PageView&noscript=1" /></noscript> <!-- DO NOT MODIFY --> <!-- End Facebook Pixel Code --> <!-- Twitter universal website tag code May 30 17 --> <script> !function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments); },s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='//static.ads-twitter.com/uwt.js', a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script'); // Insert Twitter Pixel ID and Standard Event data below twq('init','nw0gz'); twq('track','PageView'); </script> <!-- End Twitter universal website tag code --> </head> <body> <form name="aspnetForm" method="post" action="./solid-principles?ID=1365" id="aspnetForm"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE0MDk2ODQwMTdkZJysVikQVHzjAtZqOeUvZO1Bu1pl" /> </div> <div> <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="A9C58E29" /> </div> <div class="wrapper"> <!-- header --> <header class="header header-megamenu"> <nav class="navbar navbar-default" role="navigation"> <div class="container"> <!--<div class="search-bar"> <input type="search" onkeyup="executeQuery();" placeholder="Type search text here..." name="search" id="search-keyword"> <div class="search-close" id="x"><i class="fa fa-times"></i></div> </div>--> <!-- Brand and toggle get grouped for better mobile display --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <!--<a class="navbar-brand" href="./index.html"> <img src="img/dnc-logo-tee-trans.png" srcset="img/dnc-logo-small.jpg 1980w, img/dnc-logo-x-small.jpg 320w" sizes ="100vw" class="img-responsive" alt="DNC Magazine" /> </a>--> <a class="navbar-brand" href="https://www.dotnetcurry.com"> <img src="/img/dnc-logo-small.jpg" class="img-responsive" alt="DNC Magazine" /> </a> </div> <!--<div class="search-trigger pull-right"></div>--> <div class="navbar-social pull-right visible-xs-block, hidden-xs"> <a href="https://www.facebook.com/dotnetcurry"><img src="/img/icon/fb.png" class="img-responsive" alt="DotNetCurry's Official Facebook Account" /></a> <a href="https://www.twitter.com/dotnetcurry"><img src="/img/icon/twit.png" class="img-responsive" alt="DotNetCurry's Official Twitter Account" /></a> <a href="https://github.com/dotnetcurry"><img src="/img/icon/git.png" class="img-responsive" alt="DotNetCurry's Official Github Account" /></a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse navbar-ex1-collapse"> <ul class="nav navbar-nav"> <li class="dropdown megamenu"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorials <span class="fa fa-angle-down"></span></a> <ul class="dropdown-menu"> <li> <div class="row"> <div class="col-md-3"> <h5>ASP.NET</h5> <a href="https://www.dotnetcurry.com/tutorials/aspnet">ASP.NET</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-mvc">ASP.NET MVC</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-core">ASP.NET Core</a> <a href="https://www.dotnetcurry.com/tutorials/sharepoint">SharePoint</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-ajax" class="last">ASP.NET AJAX</a> <h5>Patterns and Practices</h5> <a href="https://www.dotnetcurry.com/tutorials/software-gardening">Software Gardening</a> <a href="https://www.dotnetcurry.com/tutorials/patterns-practices">Design Patterns</a> </div> <div class="col-md-3"> <h5>.NET</h5> <a href="https://www.dotnetcurry.com/tutorials/csharp">C#</a> <a href="https://www.dotnetcurry.com/tutorials/visualstudio">Visual Studio</a> <a href="https://www.dotnetcurry.com/tutorials/vsts-tfs">VSTS (Azure DevOps) & TFS</a> <a href="https://www.dotnetcurry.com/tutorials/linq">LINQ</a> <a href="https://www.dotnetcurry.com/tutorials/entityframework">Entity Framework</a> <a href="https://www.dotnetcurry.com/tutorials/dotnetframework">.NET Framework</a> <a href="https://www.dotnetcurry.com/tutorials/dotnet-standard-core">.NET Standard & .NET Core</a> <a href="https://www.dotnetcurry.com/tutorials/wpf">WPF</a> <a href="https://www.dotnetcurry.com/tutorials/wcf">WCF</a> <a href="https://www.dotnetcurry.com/tutorials/winforms">WinForms</a> </div> <div class="col-md-3"> <h5>Cloud and Mobile</h5> <a href="https://www.dotnetcurry.com/tutorials/windows-azure">Microsoft Azure</a> <a href="https://www.dotnetcurry.com/tutorials/devops">DevOps</a> <a href="https://www.dotnetcurry.com/tutorials/xamarin">Xamarin</a> <a href="https://www.dotnetcurry.com/tutorials/powershell">Powershell</a> <a href="https://www.dotnetcurry.com/tutorials/machine-learning-ai">Machine Learning & AI</a> <a href="https://www.dotnetcurry.com/tutorials/windows-store">UWP & Windows Store</a> <a href="https://www.dotnetcurry.com/tutorials/windowsphone" class="last">Windows Phone</a> <h5>Useful</h5> <a href="https://www.dotnetcurry.com/tutorials/dotnetinterview">.NET Interview Q&A</a> <a href="https://www.dotnetcurry.com/tutorials/product-articles-review">Product Reviews</a> <a href="https://www.dotnetcurry.com/tutorials/general-programming-topics">General Topics</a> </div> <div class="col-md-3"> <h5>JavaScript</h5> <a href="https://www.dotnetcurry.com/tutorials/jquery-aspnet">jQuery</a> <a href="https://www.dotnetcurry.com/tutorials/angularjs">Angular</a> <a href="https://www.dotnetcurry.com/tutorials/typescript">TypeScript</a> <a href="https://www.dotnetcurry.com/tutorials/nodejs">Node.js</a> <a href="https://www.dotnetcurry.com/tutorials/reactjs">React.js</a> <a href="https://www.dotnetcurry.com/tutorials/backbonejs">Backbone.js</a> <a href="https://www.dotnetcurry.com/tutorials/html5-javascript">HTML5 & JavaScript</a> <a href="https://www.dotnetcurry.com/tutorials/bootstrap-css">Bootstrap & CSS</a> </div> <div class="col-md-3"> <h5>Publications</h5> <a href="http://www.jquerycookbook.com/">Books</a> <a href="https://www.dotnetcurry.com/magazine/" class="last">Magazines</a> <h5>Older Technologies</h5> <a href="https://www.dotnetcurry.com/tutorials/silverlight">Silverlight</a> <a href="https://www.dotnetcurry.com/tutorials/expression-web">Expression Web</a> <a href="https://www.dotnetcurry.com/tutorials/expression-blend">Expression Blend</a> <a href="https://www.dotnetcurry.com/tutorials/windows-vista">Windows Vista</a> <a href="https://www.dotnetcurry.com/tutorials/microsoft-word">Word 2007</a> <a href="https://www.dotnetcurry.com/tutorials/microsoft-outlook">Outlook 2007</a> <a href="#"></a> </div> </div> </li> </ul> </li> <li class="dropdown megamenu"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Featured <span class="fa fa-angle-down"></span></a> <ul class="dropdown-menu"> <li> <div class="row"> <div class="col-md-3 col-xs-12"> <div class="header-post"> <a href="https://www.dotnetcurry.com/angular/1385/angular-4-cheat-sheet"> <div class="hp-thumb"> <img data-src="/img/header/1385.jpg" class="img-responsive lazyload" alt="" /> </div> </a> <date>Aug 30, 2017</date> <h4><a href="https://www.dotnetcurry.com/angular/1385/angular-4-cheat-sheet">Angular 4 Development Cheat Sheet</a></h4> <p class="hidden-xs">A quick reference guide to get you going with Angular development. It uses Angular v4 with TypeScript.</p> </div> </div> <div class="col-md-3 col-xs-12"> <div class="header-post"> <a href="https://www.dotnetcurry.com/patterns-practices/1364/error-handling-dotnet-projects"> <div class="hp-thumb"> <!-- <div class="hp-overlay"> <img src="img/header/gallery.png" alt=""/> <span>12 Photos</span> </div> --> <img data-src="/img/header/1364.jpg" class="img-responsive lazyload" alt="" /> </div> </a> <date>May 12, 2017</date> <h4><a href="https://www.dotnetcurry.com/patterns-practices/1364/error-handling-dotnet-projects">Error Handling in Large .NET Projects - Best Practices</a></h4> <p class="hidden-xs">Learn some effective error handling strategies that you can use in your .NET projects.</p> </div> </div> <div class="col-md-3 col-xs-12"> <div class="header-post"> <a href="https://www.dotnetcurry.com/patterns-practices/1375/behavior-driven-development-bdd"> <div class="hp-thumb"> <img data-src="/img/header/1375.jpg" class="img-responsive lazyload" alt="" /> </div> </a> <date>July 3, 2017</date> <h4><a href="https://www.dotnetcurry.com/patterns-practices/1375/behavior-driven-development-bdd">Behavior Driven Development (BDD) – an in-depth look</a></h4> <p class="hidden-xs">Learn how Behavior Driven Development (BDD) works with a real-world example of how to use it.</p> </div> </div> <div class="col-md-3 col-xs-12"> <div class="header-post"> <a href="https://www.dotnetcurry.com/patterns-practices/1305/aspect-oriented-programming-aop-csharp-using-solid"> <div class="hp-thumb"> <img data-src="/img/header/1305.jpg" class="img-responsive lazyload" alt="" /> </div> </a> <date>Sep 25, 2016</date> <h4><a href="https://www.dotnetcurry.com/patterns-practices/1305/aspect-oriented-programming-aop-csharp-using-solid">Aspect Oriented Programming (AOP) in C# with SOLID</a></h4> <p class="hidden-xs">Aspect Oriented Programming (AOP) in C# using SOLID principles, with challenges and solutions.</p> </div> </div> <div class="col-md-3 col-xs-12"> <div class="header-post"> <a href="https://www.dotnetcurry.com/javascript/1359/javascript-frameworks-aspnet-mvc-developer"> <div class="hp-thumb"> <img data-src="/img/header/1359.jpg" class="img-responsive lazyload" alt="" /> </div> </a> <date>Sep 25, 2016</date> <h4><a href="https://www.dotnetcurry.com/javascript/1359/javascript-frameworks-aspnet-mvc-developer">JavaScript Frameworks for ASP.NET MVC Developers</a></h4> <p class="hidden-xs">Learn about a few JavaScript frameworks, and which one will be a good fit in your ASP.NET MVC apps</p> </div> </div> </div> </li> </ul> </li> <li class="dropdown megamenu"> <a href="https://www.dotnetcurry.com/magazine/">.NET Magazines</a> </li> <li class="dropdown dropdown-v1"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">About<span class="fa fa-angle-down"></span></a> <ul class="dropdown-menu"> <li><a href="https://www.dotnetcurry.com/About.aspx">About Us</a></li> <li><a href="https://www.dotnetcurry.com/WriteForUs.aspx">Write For Us</a></li> <li><a href="https://www.dotnetcurry.com/Contact.aspx">Contact Us</a></li> </ul> </li> <!--<li class="dropdown megamenu"> <a href="https://www.dotnetcurry.net/s/dnc-products">Developer Tools</a> </li>--> </ul> </div> <!-- /.navbar-collapse --> </div> </nav> </header> <!--header--> <!-- container --> <div class="container"> <div class="clearfix divborder"> <div class="col-md-8 column"> <div class="col-md-12 articlebox row"> <div class="articletitle"> <h1 class="articlehead"> <span id="ctl00_MainContent_lblTitle">Revisiting SOLID principles</span> </h1> <b>Posted by: </b> <a id="ctl00_MainContent_lnkAddedBy" href="../../Author.aspx?AuthorName=Craig Berntson">Craig Berntson</a> , on 5/15/2017, in <b> Category </b> <a id="ctl00_MainContent_lnkCategory" href="../../BrowseArticles.aspx?CatID=82">Software Gardening</a> <br /> </div> <div class="articlestats"> <div class="stats1"> <b>Views: </b> 115363 <br/> </div> </div> <div class="articleabstract"> <b>Abstract: </b> This tutorial summarizes SOLID principles and answers some questions our viewers have asked about SOLID. </div> <div class="socialshare"> <a class="resp-sharing-button__link" id="fbsharelinktop" target="_blank" aria-label=""> <div class="resp-sharing-button resp-sharing-button--facebook resp-sharing-button--small"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M18.768,7.465H14.5V5.56c0-0.896,0.594-1.105,1.012-1.105s2.988,0,2.988,0V0.513L14.171,0.5C10.244,0.5,9.5,3.438,9.5,5.32 v2.145h-3v4h3c0,5.212,0,12,0,12h5c0,0,0-6.85,0-12h3.851L18.768,7.465z"/> </g> </svg> <span></span> </div> </div> </a> <a class="resp-sharing-button__link" id="twtsharelinktop" target="_blank" aria-label=""> <div class="resp-sharing-button resp-sharing-button--twitter resp-sharing-button--small"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M23.444,4.834c-0.814,0.363-1.5,0.375-2.228,0.016c0.938-0.562,0.981-0.957,1.32-2.019c-0.878,0.521-1.851,0.9-2.886,1.104 C18.823,3.053,17.642,2.5,16.335,2.5c-2.51,0-4.544,2.036-4.544,4.544c0,0.356,0.04,0.703,0.117,1.036 C8.132,7.891,4.783,6.082,2.542,3.332C2.151,4.003,1.927,4.784,1.927,5.617c0,1.577,0.803,2.967,2.021,3.782 C3.203,9.375,2.503,9.171,1.891,8.831C1.89,8.85,1.89,8.868,1.89,8.888c0,2.202,1.566,4.038,3.646,4.456 c-0.666,0.181-1.368,0.209-2.053,0.079c0.579,1.804,2.257,3.118,4.245,3.155C5.783,18.102,3.372,18.737,1,18.459 C3.012,19.748,5.399,20.5,7.966,20.5c8.358,0,12.928-6.924,12.928-12.929c0-0.198-0.003-0.393-0.012-0.588 C21.769,6.343,22.835,5.746,23.444,4.834z"/> </g> </svg> <span></span> </div> </div> </a> <a class="resp-sharing-button__link" id="linkdinsharelinktop" target="_blank" aria-label=""> <div class="resp-sharing-button resp-sharing-button--linkedin resp-sharing-button--small"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 21.5h-5v-13h5v13zM4 6.5C2.5 6.5 1.5 5.3 1.5 4s1-2.4 2.5-2.4c1.6 0 2.5 1 2.6 2.5 0 1.4-1 2.5-2.6 2.5zm11.5 6c-1 0-2 1-2 2v7h-5v-13h5V10s1.6-1.5 4-1.5c3 0 5 2.2 5 6.3v6.7h-5v-7c0-1-1-2-2-2z"/></svg> <span></span> </div> </div> </a> <!--<a class="resp-sharing-button__link" id="googsharelinktop" target="_blank" aria-label=""> <div class="resp-sharing-button resp-sharing-button--google resp-sharing-button--small"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M11.366,12.928c-0.729-0.516-1.393-1.273-1.404-1.505c0-0.425,0.038-0.627,0.988-1.368 c1.229-0.962,1.906-2.228,1.906-3.564c0-1.212-0.37-2.289-1.001-3.044h0.488c0.102,0,0.2-0.033,0.282-0.091l1.364-0.989 c0.169-0.121,0.24-0.338,0.176-0.536C14.102,1.635,13.918,1.5,13.709,1.5H7.608c-0.667,0-1.345,0.118-2.011,0.347 c-2.225,0.766-3.778,2.66-3.778,4.605c0,2.755,2.134,4.845,4.987,4.91c-0.056,0.22-0.084,0.434-0.084,0.645 c0,0.425,0.108,0.827,0.33,1.216c-0.026,0-0.051,0-0.079,0c-2.72,0-5.175,1.334-6.107,3.32C0.623,17.06,0.5,17.582,0.5,18.098 c0,0.501,0.129,0.984,0.382,1.438c0.585,1.046,1.843,1.861,3.544,2.289c0.877,0.223,1.82,0.335,2.8,0.335 c0.88,0,1.718-0.114,2.494-0.338c2.419-0.702,3.981-2.482,3.981-4.538C13.701,15.312,13.068,14.132,11.366,12.928z M3.66,17.443 c0-1.435,1.823-2.693,3.899-2.693h0.057c0.451,0.005,0.892,0.072,1.309,0.2c0.142,0.098,0.28,0.192,0.412,0.282 c0.962,0.656,1.597,1.088,1.774,1.783c0.041,0.175,0.063,0.35,0.063,0.519c0,1.787-1.333,2.693-3.961,2.693 C5.221,20.225,3.66,19.002,3.66,17.443z M5.551,3.89c0.324-0.371,0.75-0.566,1.227-0.566l0.055,0 c1.349,0.041,2.639,1.543,2.876,3.349c0.133,1.013-0.092,1.964-0.601,2.544C8.782,9.589,8.363,9.783,7.866,9.783H7.865H7.844 c-1.321-0.04-2.639-1.6-2.875-3.405C4.836,5.37,5.049,4.462,5.551,3.89z"/> <polygon points="23.5,9.5 20.5,9.5 20.5,6.5 18.5,6.5 18.5,9.5 15.5,9.5 15.5,11.5 18.5,11.5 18.5,14.5 20.5,14.5 20.5,11.5 23.5,11.5 "/> </g> </svg> </div> </div> </a>--> </div> </div> <div id="articleBody" class="col-md-12 row"> <p>Last year I finished up a long series on <a href="https://www.dotnetcurry.com/software-gardening/1148/solid-single-responsibility-principle" target="_blank">SOLID principles</a>.</p> <p><strong>So, what is SOLID?</strong> Well, it is five OOP principles, the first letter of each spelling out SOLID: <strong>S</strong>ingle Responsibility, <strong>O</strong>pen/Closed, <strong>L</strong>iskov Substitution, <strong>I</strong>nterface Segregation, and<strong> D</strong>ependency Inversion.</p> <p>These principles, when combined together, make it easy to develop maintainable and extensible software.</p> <p>Here at <a href="https://www.dotnetcurry.com/magazine/" target="_blank"><strong>DNC Magazine</strong></a>, we’ve had a couple of readers send questions about SOLID. This issue’s column is my attempt to answer the questions.</p> <p>Before getting to the questions, I want to summarize SOLID principles.</p> <p> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="top" width="31"> <p><b>S</b></p> </td> <td valign="top" width="539"> <p><a href="https://www.dotnetcurry.com/software-gardening/1148/solid-single-responsibility-principle" target="_blank"><strong>Single Responsibility Principle (SRP)</strong></a> – A class should have only one reason to be changed.</p> </td> </tr> <tr> <td valign="top" width="31"> <p><b>O</b></p> </td> <td valign="top" width="539"> <p><a href="https://www.dotnetcurry.com/software-gardening/1176/solid-open-closed-principle" target="_blank"><strong>Open-Closed Principle (OCP)</strong></a> – A class should be open to extension but closed to modification</p> </td> </tr> <tr> <td valign="top" width="31"> <p><b>L</b></p> </td> <td valign="top" width="539"> <p><a href="https://www.dotnetcurry.com/software-gardening/1235/liskov-substitution-principle-lsp-solid-patterns" target="_blank"><strong>Liskov Substitution Principle (LSP)</strong></a> – You should be able to replace a class with a subclass without the calling code knowing about the change</p> </td> </tr> <tr> <td valign="top" width="31"> <p><b>I</b></p> </td> <td valign="top" width="539"> <p><a href="https://www.dotnetcurry.com/software-gardening/1257/interface-segregation-principle-isp-solid-principle" target="_blank"><strong>Interface Segregation Principle (ISP)</strong></a> – Many specific interfaces are better than a single, all-encompassing interface</p> </td> </tr> <tr> <td valign="top" width="31"> <p><b>D</b></p> </td> <td valign="top" width="539"> <p><a href="https://www.dotnetcurry.com/software-gardening/1284/dependency-injection-solid-principles" target="_blank"><strong>Dependency Inversion Principle (DIP)</strong></a> – Code should depend upon abstractions, not concrete implementations</p> </td> </tr> </tbody> </table> </p> <p><img src="https://www.dotnetcurry.com/images/software-gardening/solid/solid-principles.png" alt="SOLID" width="1000" height="518" /></p> <p>Now, on to the questions.</p> <h2>SOLID for Beginners</h2> <p>The first question is from Eric, who writes,</p> <p><i>“<strong>I am a Computer Science Graduate who has learnt C#. Can you explain me SOLID (like for beginners)</strong>”?</i></p> <p>Great question, Eric. Coming out of school with a shiny degree, one can quickly realize they were taught to write code, but not taught to write software. Schools typically teach how to do things in Java, JavaScript, C#, Python and other languages but neglect the important things such as DevOps, Agile, SOLID, and other practices.</p> <p>SOLID is often difficult to understand for new developers, but yet one of the most important concepts you can understand. Where I work at Quicken Loans, we typically ask about SOLID when interviewing hiring candidates and some of them cannot give a satisfactory answer.</p> <p>The primary thing to ask yourself when writing code is, “Does this solution solve the problem?” If you can say yes, the code is correct.</p> <p>However, it may not answer other questions you need to keep in mind. These are things like:</p> <ul> <li>Does the code have adequate safe guards against invalid data?</li> <li>Is the code readable by a human?</li> <li>Is it maintainable?</li> <li>Can the code be easily extended when needs change?</li> <li>Is this code secure?</li> <li>Does the code do too much? Should I break it down into smaller pieces?</li> </ul> <p>Many of these questions can be answered by applying SOLID.</p> <p>Let’s review SOLID.</p> <p>SOLID has been around for years. The concepts were first brought together by Robert “Uncle Bob” Martin. They are a set of concepts that help us create better code.</p> <p>You shouldn’t think that code will comply with every SOLID principle the moment it leaves your fingers and enters the computer via the keyboard.</p> <p>Some principles are more applicable to interfaces, some to classes.</p> <p>And, once the code is originally written, you will typically <a href="https://www.dotnetcurry.com/software-gardening/1105/code-refactoring" target="_blank">refactor</a> it before you are satisfied that is as close to SOLID as you can get it.</p> <p>When learning SOLID, learn one principle at a time, learn it well, then move on to the next one.</p> <h3>Single Responsibility Principle</h3> <p>Single Responsibility Principle (SRP) answers many of the above questions.</p> <p>First, it can identify if code does too much. The code should do one thing and one thing only and do it well. And if code does one thing, it’s easier to understand when you read it. It’s also less likely that you’ll have to modify the code and if you do, odds are that unexpected side effects won’t creep in.</p> <p>But, it isn’t always clear what one thing code should be doing.</p> <p>Here’s an example. For many years, developers have been creating data classes. These would be used to Create, Read, Update, and Delete (CRUD) data.</p> <p>One day, someone proposed that Create, Update, and Delete are all similar in that they change data in the database.</p> <p>Read is a different animal.</p> <p>It doesn’t change data, but simply tells us what the data is, therefore, following SRP, it should be in a different class. After all, they said, it’s far more likely we’ll have to change code to read the data for different purposes than to modify the data.</p> <p>We may need a single row, multiple rows, summarized data, data sorted in different ways, totals, subtotals, counts, groupings, etc. This led to a concept called Command Query Responsibility Separation (CQRS).</p> <p>Others counteracted this by saying that in the end, it’s all data access of some kind, so it all belongs in the same class.</p> <p>Which one is correct?</p> <p>The answer is, both are correct. CQRS may add unneeded complexity.</p> <p>As a general rule, if you have to modify code in two or more places, either in the same class or multiple classes, to apply a single modification (fix a bug or add new functionality) that section of code <b><i>MIGHT</i></b> be a candidate for multiple classes, hence making it compliant with SRP.</p> <p>What if it’s only a single line of code that you move to a new class? Is the additional complexity worth it? Only you and your team can decide this.</p> <p>Here's a detailed tutorial on <a href="https://www.dotnetcurry.com/software-gardening/1148/solid-single-responsibility-principle" target="_blank">Single Responsibility Principle (SRP)</a>.</p> <h3>Open-Closed Principle</h3> <p>The Open-Closed Principle is all about adding <i>new</i> functionality without modifying the existing code or even assembly. The reason behind this is that every time you modify code, you run the risk of adding bugs to the existing functionality.</p> <p>Think about the String class in .NET.</p> <p>There are many operations that you can perform on a string. You have string.Length, string.Split, string.Substring and many others. What if there is a need to reverse all the characters in a string, so that instead of “Dot Net Curry”, you wanted, “yrruC teN, toD”?</p> <p>If the string class is modified, there is a chance (albeit very small) that existing code can get accidentally changed. Instead, create an extension method that lives in a different assembly. BAM! Done.</p> <p>Here's a detailed tutorial on <a href="https://www.dotnetcurry.com/software-gardening/1176/solid-open-closed-principle" target="_blank">Open-Closed Principle (OCP)</a>.</p> <h3>Liskov Substitution Principle</h3> <p>Now, let’s look at an oddly named principle, Liskov Substitution Principle (LSP), named after the person who first proposed it.</p> <p>What it says is that we should be able to replace a class we’re using with a subclass, and the code keeps working.</p> <p>A common example here is a logging class. Think of all the places you can write a log. It could be to a database, a file on disk, a web service, use the Windows Event Log, and others. The file on disk can take many forms. It could be plain text, XML, JSON, HTML, and many other formats.</p> <p>But the code that calls the logging methods should not have to call different methods for different ways to log. It should always call a similarly named method for all of them and a specific instance of the logging class handles the details.</p> <p>You’d have a different class for each way you support for writing a log.</p> <p>Read more in a detailed tutorial on <a href="https://www.dotnetcurry.com/software-gardening/1235/liskov-substitution-principle-lsp-solid-patterns" target="_blank">Liskov Substitution Principle (LSP)</a>.</p> <h3>Interface Segregation Principle</h3> <p>Have you ever looked at the different interfaces in the List<t> class in .Net? </t></p> <p>I have.</p> <p>List<t> inherits from eight different interfaces. Here’s the definition from MSDN. </t></p> <p><img title="list-of-t" border="0" alt="list-of-t" src="https://www.dotnetcurry.com/images/software-gardening/solid/list-of-t.jpg" width="628" height="69" /></p> <p>Why does it do this? The simple reason is to comply with the fourth SOLID principle, the Interface Segregation Principle (ISP).</p> <p>Think about the functionality defined in each of those interfaces? Now imagine if all that functionality was contained in a single interface. How complex would that be? How many different things would this single, combined interface do? It would be crazy! It would be impossible to properly maintain.</p> <p>And then imagine if you had a class that didn’t need to implement IReadOnlyList<t>. How would you implement that? Basically, you’d have code that didn’t do anything. Why do you have code that does nothing?</t></p> <p>The solution is to have many specialized interfaces so that consumers depend only on what they need.</p> <p>To delve further into ISP, here's a detailed tutorial on <a href="https://www.dotnetcurry.com/software-gardening/1257/interface-segregation-principle-isp-solid-principle" target="_blank">Interface Segregation Principle (ISP)</a>.</p> <h3>Dependency Inversion Principle</h3> <p>Let’s return to the logging example above. How do you tell a specific class which type of logging it should use? That’s the job of the Dependency Inversion Principle or as some call it Dependency Injection Principle.</p> <p>When you instantiate the class, you pass in an instance of the class you want to use through Constructor Injection.</p> <p>The following code shows how to do this.</p> <pre class="brush: csharp;"> public interface ILogger { void WriteLog(string message); } public class DatabaseLogger : ILogger { public void WriteLog(string message) { // Format message // Build parameter // Open connection // Send command // Close connection } } public class TextFileLogger : ILogger { public void WriteLog(string message) { // Format message // Open text file // Write message // Close text file } } public class Main { public Main() { var processor = new Processor(new TextFileLogger()); } } public class Processor { private readonly ILogger _logger; public Processor(ILogger logger) { _logger = logger; } public void RunProcessing() { try { // Do the processing } catch (Exception ex) { _logger.WriteLog(ex.Message); } } }</pre> <p>At the top, the interface is defined followed by two classes, DatabaseLogger and TextFile logger that implement the interface.</p> <p>In the Main class, an instance of the TextFileLogger is created and passed to the constructor of the Processor class. This is Dependency Injection. The Processor class depends on an instance of ILogger and instead of creating it every time, the instance is injected into the constructor. This also loosely couples the specific logger instance from the Processor class.</p> <p>The instance of the logger is then used inside the Try/Catch block. If you want to change the logger type, all you need to do is change the calling program so that you instantiate DatabaseLogger and send it instead.</p> <p>Further Reading - <a href="https://www.dotnetcurry.com/software-gardening/1284/dependency-injection-solid-principles" target="_blank">Dependency Inversion Principle (DIP)</a>.</p> <h3>Final thoughts on learning SOLID</h3> <p>And there you have a simplified explanation of SOLID. I encourage you to look at my earlier columns on this topic. All are linked to above. You may benefit from finding a senior level developer on your team and using him as a mentor. Mention to him that you’re interested in learning SOLID. That will help the learning curve and give you someone to rely on to help you in your early career.</p> <p>Now, onto the second question.</p> <h2>To SOLID or not to SOLID? That is the Question</h2> <p>With apologies to William Shakespeare, let’s look at the second question.</p> <p>Adam asks, <i>“When should I use SOLID and when should I not use SOLID?”</i></p> <p>Well, Adam, the easy answer is always use SOLID, but as I discussed above, it doesn’t always make sense. Sometimes it adds complexity.</p> <p>The real answer is well, more complex.</p> <p>Overly complex applications are an ugly side of software development.</p> <p>I’ve seen them over the years. I’ve tried to fix them.</p> <p>Sometimes the complexity is not in the code, but in the architectural directions taken in the application. Bad architecture is often impossible to fix without a complete rewrite.</p> <p>While SOLID is mostly a coding concept, there is an architectural aspect. Should you split something into multiple classes? How many interfaces should you use?</p> <p>This list goes on.</p> <p>Sometimes, the application of SOLID comes along as you design what the class is doing. See the above discussion on List<t>. As the designers were defining the functionality of the class, the interfaces began to take shape and they learned which ones needed to be implemented.</t></p> <p>In my work, once I have the code working correctly, I may do additional refactoring to follow a specific Design Pattern or to make the code more self-documenting. This is also a good time to look at applying some SOLID.</p> <p>Asking questions like, “Does this class do too much and if it does, will I add complexity with multiple classes?” need to be asked. You may need to discuss with your team members as it may not be obvious.</p> <p>Take the DatabaseLogger implementation above. There are five steps listed in the WriteLog method. Should each of those be a separate method? Should it be relegated to a different class? Or, should it all stay in that method?</p> <p>The answer to each of these questions is, “Maybe.”</p> <p>You may also find that the same SOLID questions come into play when modifying a class, either by adding new functionality (most likely SOLID comes into play) or fixing a bug (maybe SOLID should be used).</p> <p>There’s another situation when you may not use SOLID and that’s when you’re time restrained. Alright, I accept that <i>every</i> project is time constrained, but there are times you just need to get the code out and other times when you can “do it right”. If you’re seriously time constrained, adding the technical debt of not using SOLID when you should may be acceptable.</p> <p>But as with all technical debt, you should have a plan to pay it off.</p> <p>One final place where SOLID won’t come into play is with prototypes and throw-away code. These are both places where you don’t plan to put the code into production and it will be removed soon. Don’t spend the time worrying about SOLID here.</p> <p>Now, having said all this, as you gain experience, you start to see how to use SOLID earlier in the architectural and code writing process. Not all the time. You’ll still have programming puzzles that require you to refactor to SOLID, but because of accumulated experience, you should be able to complete the refactoring more quickly and with better results.</p> <h3>Conclusion</h3> <p>As with many software development concepts, SOLID has a place in your toolbox. It has a learning curve as steep as there is, but it’s one to master, not only learning the principles but when to use them and when not to use them. And by understanding SOLID and using it properly your software can be green, lush, and growing.</p> <p><strong>About Software Gardening</strong></p> <p>Comparing software development to constructing a building says that software is solid and difficult to change. Instead, we should compare software development to gardening as a garden changes all the time. Software Gardening embraces practices and tools that help you create the best possible garden for your software, allowing it to grow and change with less effort.</p> <p>Learn more about <a href="https://www.dotnetcurry.com/tutorials/software-gardening">Software Gardening</a>.</p> <p><em>This article was technically reviewed by </em><a href="https://www.dotnetcurry.com/author/yacoub-massad"><strong><em>Yacoub Massad</em></strong></a><em>.</em></p> <p><em>This article has been editorially reviewed by </em><a href="https://www.dotnetcurry.com/author/suprotim-agarwal"><em>Suprotim Agarwal.</em></a></p> <div id="csharpbook" class="col-xs-12 col-sm-12 col-md-12 col-lg-12 articletext"> <!--<a href="http://www.dotnetcurry.org/r/dnc-csharpbk-web-imgbtm" target="_blank" style="color:#cd282f"><img alt="Absolutely Awesome Book on C# and .NET" src="/csharpbook/images/csharpbook-hori.jpg" /></a>--> <div class="col-md-3 col-sm-3 col-xs-12"> <a href="https://www.dotnetcurry.com/csharpbook" target="_blank"><img alt="Absolutely Awesome Book on C# and .NET" src="/csharpbook/images/csharp-book-ad.jpg" /></a> </div> <div class="col-md-9 col-sm-9 col-xs-12"> <p>C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.</p> <p>We at DotNetCurry are very excited to announce <strong><a href="https://www.dotnetcurry.com/csharpbook" target="_blank">The Absolutely Awesome Book on C# and .NET</a></strong>. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle). </p><p>Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering <b>C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too</b>. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.</p> <p><strong><a href="https://www.dotnetcurry.com/csharpbook" target="_blank" style="color:#cd282f">Click here to Explore the Table of Contents or Download Sample Chapters!<a /></strong></p> </div> </div> <div class="footerheading margin-top-20">What Others Are Reading!</div> <div class="col-xs-12 col-sm-12 col-md-12 similarauthor"> <div class="row"> <div class="col-md-12 similararticles"> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1351" style="color:#4A75AD;font-weight:normal;">Reduce Bad Code with Code Reviews</a> <br /><br /> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1333" style="color:#4A75AD;font-weight:normal;">Coding Guidelines - Important for Developers</a> <br /><br /> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1284" style="color:#4A75AD;font-weight:normal;">Dependency Injection - SOLID Principles</a> <br /><br /> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1257" style="color:#4A75AD;font-weight:normal;">SOLID: Interface Segregation Principle (Part 4)</a> <br /><br /> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1235" style="color:#4A75AD;font-weight:normal;">SOLID: Liskov Substitution Principle (Software Gardening)</a> <br /><br /> <a href="http://www.dotnetcurry.com/ShowArticle.aspx?ID=1176" style="color:#4A75AD;font-weight:normal;">Open-Closed Principle (Software Gardening: Seeds)</a> <br /><br /> <span id="ctl00_MainContent_SimilarPosts1_lblCategoNam"></span> </div> </div> </div> <!-- DNC_BottomText --> <div class="visible-xs visible-sm visible-md visible-lg"> <div id='dnc-bot-txtad' class="articletext"> </div> </div> <div class="socialbox"> <b>Was this article worth reading? Share it with fellow developers too. Thanks!</b> <br/> <!-- Sharingbutton Facebook --> <a class="resp-sharing-button__link" id="fbsharelink" target="_blank" aria-label="Share on Facebook"> <div class="resp-sharing-button resp-sharing-button--facebook resp-sharing-button--large"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M18.768,7.465H14.5V5.56c0-0.896,0.594-1.105,1.012-1.105s2.988,0,2.988,0V0.513L14.171,0.5C10.244,0.5,9.5,3.438,9.5,5.32 v2.145h-3v4h3c0,5.212,0,12,0,12h5c0,0,0-6.85,0-12h3.851L18.768,7.465z"/> </g> </svg> </div>Share on Facebook</div> </a> <!-- Sharingbutton Twitter --> <a class="resp-sharing-button__link" id="twtsharelink" target="_blank" aria-label="Share on Twitter"> <div class="resp-sharing-button resp-sharing-button--twitter resp-sharing-button--large"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M23.444,4.834c-0.814,0.363-1.5,0.375-2.228,0.016c0.938-0.562,0.981-0.957,1.32-2.019c-0.878,0.521-1.851,0.9-2.886,1.104 C18.823,3.053,17.642,2.5,16.335,2.5c-2.51,0-4.544,2.036-4.544,4.544c0,0.356,0.04,0.703,0.117,1.036 C8.132,7.891,4.783,6.082,2.542,3.332C2.151,4.003,1.927,4.784,1.927,5.617c0,1.577,0.803,2.967,2.021,3.782 C3.203,9.375,2.503,9.171,1.891,8.831C1.89,8.85,1.89,8.868,1.89,8.888c0,2.202,1.566,4.038,3.646,4.456 c-0.666,0.181-1.368,0.209-2.053,0.079c0.579,1.804,2.257,3.118,4.245,3.155C5.783,18.102,3.372,18.737,1,18.459 C3.012,19.748,5.399,20.5,7.966,20.5c8.358,0,12.928-6.924,12.928-12.929c0-0.198-0.003-0.393-0.012-0.588 C21.769,6.343,22.835,5.746,23.444,4.834z"/> </g> </svg> </div>Share on Twitter</div> </a> <!-- Sharingbutton LinkedIn --> <a class="resp-sharing-button__link" id="linkdinsharelink" target="_blank" aria-label="Share on LinkedIn"> <div class="resp-sharing-button resp-sharing-button--linkedin resp-sharing-button--large"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg xmlns="https://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6.5 21.5h-5v-13h5v13zM4 6.5C2.5 6.5 1.5 5.3 1.5 4s1-2.4 2.5-2.4c1.6 0 2.5 1 2.6 2.5 0 1.4-1 2.5-2.6 2.5zm11.5 6c-1 0-2 1-2 2v7h-5v-13h5V10s1.6-1.5 4-1.5c3 0 5 2.2 5 6.3v6.7h-5v-7c0-1-1-2-2-2z"/></svg> </div>Share on LinkedIn</div> </a> <!-- Sharingbutton Google+ --> <a class="resp-sharing-button__link" id="googsharelink" target="_blank" aria-label="Share on Google+"> <div class="resp-sharing-button resp-sharing-button--google resp-sharing-button--large"><div aria-hidden="true" class="resp-sharing-button__icon resp-sharing-button__icon--solid"> <svg version="1.1" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve"> <g> <path d="M11.366,12.928c-0.729-0.516-1.393-1.273-1.404-1.505c0-0.425,0.038-0.627,0.988-1.368 c1.229-0.962,1.906-2.228,1.906-3.564c0-1.212-0.37-2.289-1.001-3.044h0.488c0.102,0,0.2-0.033,0.282-0.091l1.364-0.989 c0.169-0.121,0.24-0.338,0.176-0.536C14.102,1.635,13.918,1.5,13.709,1.5H7.608c-0.667,0-1.345,0.118-2.011,0.347 c-2.225,0.766-3.778,2.66-3.778,4.605c0,2.755,2.134,4.845,4.987,4.91c-0.056,0.22-0.084,0.434-0.084,0.645 c0,0.425,0.108,0.827,0.33,1.216c-0.026,0-0.051,0-0.079,0c-2.72,0-5.175,1.334-6.107,3.32C0.623,17.06,0.5,17.582,0.5,18.098 c0,0.501,0.129,0.984,0.382,1.438c0.585,1.046,1.843,1.861,3.544,2.289c0.877,0.223,1.82,0.335,2.8,0.335 c0.88,0,1.718-0.114,2.494-0.338c2.419-0.702,3.981-2.482,3.981-4.538C13.701,15.312,13.068,14.132,11.366,12.928z M3.66,17.443 c0-1.435,1.823-2.693,3.899-2.693h0.057c0.451,0.005,0.892,0.072,1.309,0.2c0.142,0.098,0.28,0.192,0.412,0.282 c0.962,0.656,1.597,1.088,1.774,1.783c0.041,0.175,0.063,0.35,0.063,0.519c0,1.787-1.333,2.693-3.961,2.693 C5.221,20.225,3.66,19.002,3.66,17.443z M5.551,3.89c0.324-0.371,0.75-0.566,1.227-0.566l0.055,0 c1.349,0.041,2.639,1.543,2.876,3.349c0.133,1.013-0.092,1.964-0.601,2.544C8.782,9.589,8.363,9.783,7.866,9.783H7.865H7.844 c-1.321-0.04-2.639-1.6-2.875-3.405C4.836,5.37,5.049,4.462,5.551,3.89z"/> <polygon points="23.5,9.5 20.5,9.5 20.5,6.5 18.5,6.5 18.5,9.5 15.5,9.5 15.5,11.5 18.5,11.5 18.5,14.5 20.5,14.5 20.5,11.5 23.5,11.5 "/> </g> </svg> </div>Share on Google+</div> </a> <!--<ul class="socialshare"> <li><div class="gplusarticle"><b>Please Share this article if you think it was worth reading. Thanks!</b></div></li> <li><div class="fb-share-button" data-layout="button"> </div> </li> <li><script type="IN/Share"></script></li> </ul>--> </div> <br /> <div class="col-xs-12 col-sm-12 col-md-12 similarauthor"> <div class="row footerheading">Author</div> <div class="row"> <div class="col-md-12"> <div class="col-md-12 author-wrap img-rounded"> <div class="author-image thumbnail"> <img id="ctl00_MainContent_authorInfo_imgAuthor" onerror="this.onload = null; this.src='/images/authors/NoImage.jpg';" src="../../images/authors/Craig%20Berntson.jpg" style="border-width:0px;" /> </div> <div class="author-desc caption"> Craig Berntson is a software architect specializing in breaking up the monolith and improving developer teams and processes. He is the author of two books on software development and has been a speaker at conferences across North America and Europe. He received the Microsoft MVP award twenty-two straight years. He lives in Salt Lake City, Utah. </div> </div> </div> </div> </div> </div> <!--<div class="footerheading">Further Reading - Articles You May Like!</div>--> <div class="marginspace"> <div id='ban-pos-9-90'></div> <div id='ban-pos-10-90'></div> <div id='ban-pos-11-90'></div> </div> <br /><br /> <div class="col-xs-12 col-sm-12 col-md-12"> <!--<a href="http://www.copyscape.com/" target="blank" rel="nofollow">--><img src="/images/copyscape.gif" alt="Page copy protected against web site content infringement by Copyscape" title="Do not copy content from the page. Plagiarism will be detected by Copyscape." height="16" border="0"/><!--</a>--> </div> <br /><br /> <br /> <hr /> <div id="ctl00_MainContent_panComments" class="col-md-12 spacer"> <div class="footerheading">Feedback - Leave us some adulation, criticism and everything in between!</div> <ul class="tabHeader"> <li><a class="show-comments" href="#t1">Click here to post your Comments</a> </li> </ul> <div class="tabContent"> <div id="t1" class="col-md-12 column"> <div id="disqus_thread"></div> <!--<script type="text/javascript"> var disqus_shortname = 'dotnetcurry'; /* * * DON'T EDIT BELOW THIS LINE * * */ (function () { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); </script> <noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> <a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>--> </div> <div id="t2"> </div> <!-- t2 --> </div> <!-- tabcontent --> </div> <!-- Place this render call where appropriate <script type="text/javascript"> (function () { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); </script> <script src="//platform.linkedin.com/in.js" type="text/javascript"> lang: en_US</script> <script> !function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (!d.getElementById(id)) { js = d.createElement(s); js.id = id; js.src = "//platform.twitter.com/widgets.js"; fjs.parentNode.insertBefore(js, fjs); } } (document, "script", "twitter-wjs");</script>--> <!-- Finally, to actually run the highlighter, you need to include this JS on your page --> </div> <div id="rightcol" class="col-md-4"> <!-- <div class="row"> <div class="spacerforsearch"> <div class="input-group"> <input name="ctl00$searchbox" id="ctl00_searchbox" type="text" class="form-control" placeholder="Search DotNetCurry.com for..." onFocus="this.className = 'form-control'" style="border-color:#94C7EF;border-width:1px;border-style:solid;width:100%" /> <span class="input-group-btn"> <input type="submit" name="ctl00$SearchButton" value="Go!" id="ctl00_SearchButton" class="btn btn-default" type="button" /> </span> </div> </div> </div> --> <div class="margin-vertical-20" /> <div class="side-widget"> <div class="featured-tools"> <span>Featured Tools</span> <div id="creatives"> <div id='ban-pos-1' style='display: none'> </div> <div id='ban-pos-2'> <div class="padding-vertical-10"></div> </div> <div id='ban-pos-3'> </div> <div class="padding-vertical-10"></div> <div id='ban-pos-4-250'> </div> <div id='ban-pos-5-250'> </div> <div id='ban-pos-6-250'> </div> </div> </div> </div> <div class="sec-title"> <h4>Categories</h4> </div> <div class="side-widget"> <ul id="toggle-view"> <li> <h3>.NET Web</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/aspnet">ASP.NET</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-mvc">ASP.NET MVC</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/aspnet-core">ASP.NET Core</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-ajax">ASP.NET AJAX</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/sharepoint">SharePoint</a> <a href="https://www.dotnetcurry.com/tutorials/wcf">WCF</a> </div> </div> </li> <li> <h3>.NET Framework, Visual Studio and C#</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/csharp">C#</a> <a href="https://www.dotnetcurry.com/tutorials/linq">LINQ</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/visualstudio">Visual Studio</a> <a href="https://www.dotnetcurry.com/tutorials/vsts-tfs">VSTS & TFS</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/entityframework">Entity Framework</a> <a href="https://www.dotnetcurry.com/tutorials/dotnetframework">.NET Framework</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/dotnet-standard-core">.NET Standard & .NET Core</a> </div> </div> </li> <li> <h3>Patterns & Practices</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/patterns-practices">Design Patterns</a> <a href="https://www.dotnetcurry.com/tutorials/software-gardening">Software Gardening</a> </div> </div> </li> <li> <h3>Cloud and Mobile</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/windows-azure">Microsoft Azure</a> <a href="https://www.dotnetcurry.com/tutorials/xamarin">Xamarin</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/powershell">Powershell</a> <a href="https://www.dotnetcurry.com/tutorials/machine-learning-ai">Machine Learning & AI</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/windows-store">UWP & Windows Store</a> <a href="https://www.dotnetcurry.com/tutorials/windowsphone">Windows Phone</a> </div> </div> </li> <li> <h3>JavaScript</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/typescript">TypeScript</a> <a href="https://www.dotnetcurry.com/tutorials/angularjs">Angular</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/jquery-aspnet">jQuery</a> <a href="https://www.dotnetcurry.com/tutorials/nodejs">Node.js</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/reactjs">React.js</a> <a href="https://www.dotnetcurry.com/tutorials/backbonejs">Backbone.js</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/html5-javascript">HTML5 & JavaScript</a> <a href="https://www.dotnetcurry.com/tutorials/bootstrap-css">Bootstrap & CSS</a> </div> </div> </li> <li> <h3>.NET Desktop</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/wpf">WPF</a> <a href="https://www.dotnetcurry.com/tutorials/winforms">WinForms</a> </div> </div> </li> <li> <h3>Interview Questions & Product Reviews</h3> <span class="fa fa-angle-down"></span> <div class="toggle-panel"> <div> <a href="https://www.dotnetcurry.com/tutorials/dotnetinterview">.NET Interview Q&A</a> <a href="https://www.dotnetcurry.com/tutorials/product-articles-review">Product Reviews</a> </div> <div> <a href="https://www.dotnetcurry.com/tutorials/general-programming-topics">General Topics</a> </div> </div> </li> </ul> </div> <div class="sec-title"> <h3><b>JOIN OUR COMMUNITY</b></h3> </div> <div class="side-widget"> <div class="side-social"> <a href="https://www.facebook.com/dotnetcurry"><i class="fa fa-facebook"></i> 50K+ <span>fans</span></a> <a href="https://www.twitter.com/dotnetcurry"><i class="fa fa-twitter"></i> 8K+ <span>followers</span></a> <a href="https://www.dotnetcurry.com/magazine/"><i class="fa fa-envelope"></i> 128K+ <span>subscribers</span></a> </div> </div> <div class="sec-title"> <h3><b>POPULAR ARTICLES</b></h3> </div> <div id="latestart" class="side-widget"> <div> <br /> <br /> <br /> </div> </div> <div id='ban-pos-7-600'> </div> <div id='ban-pos-8-600'> </div> <div class="sec-title-plain"> <h4>Tags</h4> </div> <div class="side-widget"> <div class="tags"> <a href="https://www.dotnetcurry.com/tutorials/aspnet-mvc">ASP.NET MVC</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet-core">ASP.NET Core</a> <a href="https://www.dotnetcurry.com/tutorials/aspnet">ASP.NET</a> <a href="https://www.dotnetcurry.com/tutorials/sharepoint">SharePoint</a> <a href="https://www.dotnetcurry.com/tutorials/patterns-practices">Design Patterns</a> <a href="https://www.dotnetcurry.com/tutorials/csharp">C#</a> <a href="https://www.dotnetcurry.com/tutorials/linq">LINQ</a> <a href="https://www.dotnetcurry.com/tutorials/wpf">WPF</a> <a href="https://www.dotnetcurry.com/tutorials/wcf">WCF</a> <a href="https://www.dotnetcurry.com/tutorials/visualstudio">Visual Studio</a> <a href="https://www.dotnetcurry.com/tutorials/vsts-tfs">VSTS & TFS</a> <a href="https://www.dotnetcurry.com/tutorials/windows-azure">Azure</a> <a href="https://www.dotnetcurry.com/tutorials/entityframework">Entity Framework</a> <a href="https://www.dotnetcurry.com/tutorials/angularjs">Angular.js</a> <a href="https://www.dotnetcurry.com/tutorials/reactjs">React.js</a> <a href="https://www.dotnetcurry.com/tutorials/jquery-aspnet">jQuery</a> <a href="https://www.dotnetcurry.com/tutorials/html5-javascript">JavaScript</a> <a href="https://www.dotnetcurry.com/tutorials/html5-javascript">HTML5</a> <a href="https://www.dotnetcurry.com/tutorials/dotnet-standard-core">.NET Core</a> <a href="https://www.dotnetcurry.com/tutorials/dotnetframework">.NET Framework</a> </div> </div> <div class="sec-title"> <h3><b>JQUERY COOKBOOK</b></h3> </div> <div class="side-widget"> <a href="http://www.jquerycookbook.com"><img src="https://www.dotnetcurry.com/images/books/300x300-jqckbk.png" alt="jQuery CookBook" /></a> </div> </div> </div> </div> <!-- container --> </div> <!-- footer --> <footer class="margin-top-30"> <div class="container"> <div class="footer-head"> <div class="row center-content"> <div class="col-md-2 col-sm-3"> <a href="https://www.dotnetcurry.com"> <img data-src="/img/dnc-logo-tee-trans.png" class="img-responsive lazyload" alt="" /> </a> </div> <div class="col-md-6 col-sm-4"> <p></p> </div> <!--<div class="col-md-4 col-sm-5"> <form class="footer-search"> <input type="search" placeholder="Search"> <button type="submit"><i class="fa fa-search"></i></button> </form> </div>--> </div> </div> <div class="footer-content"> <div class="row"> <div class="col-sm-2"> <h5 class="text-white">Server-Side</h5> <ul class="footer-links"> <li><a href="https://www.dotnetcurry.com/tutorials/aspnet">ASP.NET</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/aspnet-core">ASP.NET Core</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/aspnet-mvc">ASP.NET MVC</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/wcf">WCF</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/sharepoint">SharePoint</a></li> </ul> </div> <div class="col-sm-2"> <h5 class="text-white">Client-side</h5> <ul class="footer-links"> <li><a href="https://www.dotnetcurry.com/tutorials/angularjs">Angular.js</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/reactjs">React.js</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/jquery-aspnet">jQuery</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/backbonejs">Backbone.js</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/html5-javascript">HTML5</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/bootstrap-css">CSS</a></li> </ul> </div> <div class="col-sm-2"> <h5 class="text-white">.NET</h5> <ul class="footer-links"> <li><a href="https://www.dotnetcurry.com/tutorials/csharp">C#</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/visualstudio">Visual Studio</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/vsts-tfs">VSTS & TFS</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/linq">LINQ</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/entityframework">Entity Framework</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/dotnetframework">.NET Framework</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/dotnet-standard-core">.NET Standard & .NET Core</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/wpf">WPF</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/winforms">WinForms</a></li> </ul> </div> <div class="col-sm-2"> <h5 class="text-white">Cloud and Mobile</h5> <ul class="footer-links"> <li><a href="https://www.dotnetcurry.com/tutorials/windows-azure">Microsoft Azure</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/devops">DevOps</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/xamarin">Xamarin</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/powershell">Powershell</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/machine-learning-ai">Machine Learning & AI</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/windows-store">UWP & Windows Store</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/windowsphone">Windows Phone</a></li> </ul> </div> <div class="col-sm-2"> <h5 class="text-white">Skill Up</h5> <ul class="footer-links"> <li><a href="https://www.dotnetcurry.com/tutorials/patterns-practices">Design Patterns</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/software-gardening">Software Gardening</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/dotnetinterview">.NET Interview Q&A</a></li> <li><a href="https://www.dotnetcurry.com/magazine/" class="last">Magazines</a></li> <li><a href="http://www.jquerycookbook.com/">Books</a></li> <li><a href="https://www.dotnetcurry.com/tutorials/product-articles-review">Product Reviews</a></li> </ul> </div> <div class="col-sm-2"> <h5 class="text-white">Follow Us</h5> <ul class="footer-social"> <li><a href="https://www.facebook.com/dotnetcurry">Facebook</a></li> <li><a href="https://www.twitter.com/dotnetcurry">Twitter</a></li> <li><a href="https://github.com/dotnetcurry">Github</a></li> </ul> </div> </div> </div> <div class="footer-bottom"> <div class="row"> <div class="col-sm-6"> <p>© 2007-2023 DotNetCurry.com (A subsidiary of A2Z Knowledge Visuals Pvt. Ltd). All rights reserved.</p> </div> <div class="col-sm-6 text-right"> <ul class="list-inline"> <li><a href="https://www.dotnetcurry.com/Contact.aspx">Contact Us</a></li> <li><a href="https://www.dotnetcurry.com/WriteForUs.aspx">Write For Us</a></li> <li><a href="https://www.dotnetcurry.com/PrivacyPolicy.aspx">Privacy</a></li> <li><a href="https://www.dotnetcurry.com/terms-conditions">Terms</a></li> </ul> </div> </div> </div> </div> </footer> <!-- footer --> </form> <script src="//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js"></script> <script src="/bundles/scriptsmin?v=ztXW8lGCJchjv7iQbaTOZjTpSGfOrLg1lKllrWansXI1"></script> <script src="/bundles/framework?v=yOkBizHgoWwNt4OFd4FauUxu9fucEJ_a4EJrci8uIGA1"></script> <script type="text/javascript"> SyntaxHighlighter.defaults['auto-links'] = false; SyntaxHighlighter.defaults['gutter'] = false; SyntaxHighlighter.defaults['toolbar'] = false; SyntaxHighlighter.all() </script> <script> $(function () { $('.tabHeader').children().first().addClass('current'); $('.tabContent').children().first().addClass('current'); $('.tabHeader li').click(function (e) { e.preventDefault(); $(this).siblings('.current').removeClass('current'); $(this).addClass('current'); $('.tabContent').children('.current').removeClass('current'); $('.tabContent').children().eq($(this).index()).addClass('current'); }); }); </script> <script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js"></script> <script> WebFont.load({ google: { families: ['Hind Vadodara:300,400,500,600,700'] } }); </script> </body> </html>