
{"id":372,"date":"2009-12-11T23:00:55","date_gmt":"2009-12-12T04:00:55","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=372"},"modified":"2009-12-11T23:00:55","modified_gmt":"2009-12-12T04:00:55","slug":"public-classes-protected-methods-and-limitations-of-c-visibility-control","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=372","title":{"rendered":"Public Classes, Protected Methods and Limitations of C# Visibility Control"},"content":{"rendered":"<p>I had an interesting problem today. I had a public class in my assembly called <code>Session<\/code>. It was a public class, but it used a lot of internal stuff in the implementation. It went something like this:<\/p>\n<div style=\"border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt\">\n<div style=\"background-color: #ffffff; overflow: auto; padding: 2px 5px;\"><span style=\"color:#0000ff\">public<\/span> <span style=\"color:#0000ff\">class<\/span> <span style=\"color:#2b91af\">Session<\/span><br \/>\n{<br \/>\n&#160;&#160;&#160;&#160;(<span style=\"color:#0000ff\">public<\/span> methods and properties here)<\/p>\n<p>&#160;&#160;&#160;&#160;<span style=\"color:#0000ff\">private<\/span> <span style=\"color:#0000ff\">void<\/span> HandleResponse(Response response) <span style=\"color:#008000\">\/\/ Response class is internal<\/span><br \/>\n&#160;&#160;&#160;&#160;{<br \/>\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#8230;<br \/>\n&#160;&#160;&#160;&#160;}<br \/>\n}<\/div>\n<\/div>\n<p>Later I needed to split it into two classes: <code>MarketDataSession<\/code> and <code>TradeSession<\/code>. They have a lot in common, but they need to handle responses slightly differently. I decided to keep shared functionality in <code>Session<\/code> making it a base class. So, I modified Session like this:<\/p>\n<div style=\"border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt\">\n<div style=\"background-color: #ffffff; overflow: auto; padding: 2px 5px;\"><span style=\"color:#0000ff\">public<\/span> <span style=\"color:#0000ff\">class<\/span> <span style=\"color:#2b91af\">Session<\/span><br \/>\n{<br \/>\n&#160;&#160;&#160;&#160;(<span style=\"color:#0000ff\">public<\/span> methods and properties here)<\/p>\n<p>&#160;&#160;&#160;&#160;<span style=\"color:#0000ff\">protected<\/span> <span style=\"color:#0000ff\">virtual<\/span> <span style=\"color:#0000ff\">void<\/span> HandleResponse(Response response) <span style=\"color:#008000\">\/\/ Response class is internal<\/span><br \/>\n&#160;&#160;&#160;&#160;{<br \/>\n&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#8230;<br \/>\n&#160;&#160;&#160;&#160;}<br \/>\n}<\/p>\n<p><span style=\"color:#0000ff\">public<\/span> <span style=\"color:#0000ff\">class<\/span> <span style=\"color:#2b91af\">TradeSession<\/span> : Session &#8230;<br \/>\n<span style=\"color:#0000ff\">public<\/span> <span style=\"color:#0000ff\">class<\/span> <span style=\"color:#2b91af\">MarketDataSession<\/span> : Session &#8230;<\/div>\n<\/div>\n<p>I immediately ran into trouble: inconsistent accessibility, <code>Response<\/code> class is less accessible then method <code>HandleResponse<\/code>. Indeed, <code>HandleResponse<\/code> is now a protected method of a public class, so theoretically it can be overriden outside of the assembly.<\/p>\n<p>I could make <code>Session<\/code> an internal class, but public classes <code>TradeSession<\/code> and <code>MarketDataSession<\/code> are not allowed to derive from an internal class.<\/p>\n<p>The only solution that allows me to keep <code>Response<\/code> class internal is to mark <code>HandleResponse<\/code> method as internal. This makes it invisible from outside of the assembly, but now it is wide open inside the assembly, which is also not so stellar.<\/p>\n<p>There is another, rarely used access control option, <code>protected internal<\/code>, but it actually means protected <b>OR<\/b> internal, i.e. the method is accessible to anyone inside the assembly and to derived classes outside of the assembly.<\/p>\n<p>What I need here is protected <b>AND<\/b> internal: accessible only to derived classes within the same assembly. AFAIK, this option exists in IL and in C++\/CLI as <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/45x418az%28VS.80%29.aspx\"><code>private protected<\/code> <\/a>. Here&#8217;s a real example where it would be useful in C#.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had an interesting problem today. I had a public class in my assembly called Session. It was a public class, but it used a lot of internal stuff in <a href=\"https:\/\/ikriv.com\/blog\/?p=372\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[8],"tags":[],"class_list":["entry","author-ikriv","post-372","post","type-post","status-publish","format-standard","category-cs"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/372","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=372"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/372\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=372"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=372"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=372"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}