{"id":3043,"date":"2010-04-26T08:58:00","date_gmt":"2010-04-26T08:58:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/breaking-through-the-class-sealing\/"},"modified":"2016-07-28T10:49:58","modified_gmt":"2016-07-28T10:49:58","slug":"breaking-through-the-class-sealing","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/breaking-through-the-class-sealing\/","title":{"rendered":"Breaking through the class sealing"},"content":{"rendered":"<p>Do you understand &#8216;sealing&#8217; in C#?  Somewhat?  Anyway, here&#8217;s the lowdown.<\/p>\n<p>I&#8217;ve done this article from a C# perspective, but I&#8217;ve occasionally referenced .NET when appropriate.<\/p>\n<h4>What is sealing a class?<\/h4>\n<p>By sealing a class in C#, you ensure that you ensure that no class can be derived from that class.  You do this by simply adding the word &#8216;sealed&#8217; to a class definition: public sealed class Dog {}<\/p>\n<p>Now writing something like &#8221; public sealed class Hamster: Dog {} &#8221; you&#8217;ll get a compile error like this:<\/p>\n<p>&#8216;Hamster: cannot derive from sealed type &#8216;Dog&#8217;<\/p>\n<p>If you look in an IL disassembler, you&#8217;ll see a definition like this:<\/p>\n<pre>.class public auto ansi sealed beforefieldinit Dog extends [mscorlib]System.Object<\/pre>\n<\/p>\n<p>Note the addition of the word &#8216;sealed&#8217;.<\/p>\n<h4>What about sealing methods?<\/h4>\n<p>You can also seal overriding methods.  By adding the word &#8216;sealed&#8217;, you ensure that the method cannot be overridden in a derived class.  Consider the following code:<\/p>\n<p>public class Dog : Mammal { public sealed override void Go() { } }      <br \/>public class Mammal { public virtual void Go() { } }<\/p>\n<p>In this code, the method &#8216;Go&#8217; in Dog is sealed.  It cannot be overridden in a subclass.  Writing this would cause a compile error:<\/p>\n<p>public class Dachshund : Dog { public override void Go() { } }<\/p>\n<p>However, we can &#8216;new&#8217; a method with the same name.  This is essentially a new method; distinct from the &#8216;Go&#8217; in the subclass:<\/p>\n<p>public class Terrier : Dog { public new void Go() { } } <\/p>\n<h4>Sealing properties?<\/h4>\n<p>You can also seal seal properties.  You add &#8216;sealed&#8217; to the property definition, like so:<\/p>\n<p>public sealed override string Name      <br \/>{       <br \/>    get { return m_Name; }       <br \/>    set { m_Name = value; }       <br \/>}<\/p>\n<p>In C#, you can only seal a property, not the underlying setters\/getters.  This is because C# offers no override syntax for setters or getters.  However, in underlying IL you seal the setter and getter methods individually &#8211; a property is just metadata.<\/p>\n<\/p>\n<h4>Why bother sealing?<\/h4>\n<p>There are a few traditional reasons to seal:<\/p>\n<ol>\n<li><strong>Invariance. <\/strong>Other people may want to derive from your class, even though your implementation may make successful derivation near-impossible.  There may be twisted, hacky logic that could never be second-guessed by another developer.  By sealing your class, you&#8217;re protecting them from wasting their time.  The CLR team has sealed most of the framework classes, and I assume they did this for this reason. <\/li>\n<li><strong>Security.<\/strong>  By deriving from your type, an attacker may gain access to functionality that enables him to hack your system.  I consider this a very weak security precaution. <\/li>\n<li><strong>Speed.<\/strong>  If a class is sealed, then .NET doesn&#8217;t need to consult the virtual-function-call table to find the actual type, since it knows that no derived type can exist.  Therefore, it could emit a &#8216;call&#8217; instead of &#8216;callvirt&#8217; or at least optimise the machine code, thus producing a performance benefit.  But I&#8217;ve done trials, and have been unable to demonstrate this If you have an example, please share!<\/li>\n<\/ol>\n<p>All in all, I&#8217;m not convinced that sealing is interesting or important.  Anyway, moving-on&#8230;<\/p>\n<h4>What is automatically sealed?<\/h4>\n<ol>\n<li><strong>Value types and structs.<\/strong>  If they were not always sealed, all sorts of things would go wrong.  For instance, structs are laid-out inline within a class.  But what if you assigned a substruct to a struct field of that class?  There may be too many fields to fit.<\/li>\n<li><strong>Static classes.<\/strong>  Static classes exist in C# but not .NET.  The C# compiler compiles a static class into an &#8216;abstract sealed&#8217; class.  So static classes are already sealed in C#.<\/li>\n<li><strong>Enumerations.<\/strong>  The CLR does not track the types of enumerations &#8211; it treats them as simple value types.  Hence, polymorphism would not work.<\/li>\n<\/ol>\n<h4>What cannot be sealed?<\/h4>\n<ol>\n<li>\n<p><strong>Interfaces.<\/strong>  Interfaces exist to be implemented, so sealing to prevent implementation is dumb.  But what if you could prevent interfaces from being extended (i.e. ban declarations like &#8220;public interface IMyInterface : ISealedInterface&#8221;)?  There is no good reason to seal an interface like this.  Sealing finalizes behaviour, but interfaces have no intrinsic behaviour to finalize<\/p>\n<\/li>\n<li>\n<p><strong>Abstract classes.<\/strong>  In IL you <em>can<\/em> create an abstract sealed class.  But C# syntax for this already exists &#8211; declaring a class as a &#8216;static&#8217;, so it forces you to declare it as such.<\/p>\n<\/li>\n<li>\n<p><strong>Non-override methods.<\/strong>  If a method isn&#8217;t declared as override it cannot be overridden, so sealing would make no difference.  Note this is stated from a C# perspective &#8211; the words are opposite in IL.  In IL, you have four choices in total: no declaration (which actually seals the method), &#8216;virtual&#8217; (called &#8216;override&#8217; in C#), &#8216;sealed virtual&#8217; (&#8216;sealed override&#8217; in C#) and &#8216;newslot virtual&#8217; (&#8216;new virtual&#8217; or &#8216;virtual&#8217; in C#, depending on whether the method already exists in a base class).<\/p>\n<\/li>\n<li>\n<p><strong>Methods that implement interface methods.<\/strong>  Methods that implement an interface method must be virtual, so cannot be sealed.<\/p>\n<\/li>\n<li>\n<p><strong>Fields<\/strong>.  A field cannot be overridden, only hidden (using the &#8216;new&#8217; keyword in C#), so sealing would make no sense.<\/p>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Do you understand &#8216;sealing&#8217; in C#? Somewhat? Anyway, here&#8217;s the lowdown. I&#8217;ve done this article from a C# perspective, but I&#8217;ve occasionally referenced .NET when appropriate. What is sealing a class? By sealing a class in C#, you ensure that you ensure that no class can be derived from that class. You do this by&#8230;&hellip;<\/p>\n","protected":false},"author":95472,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-3043","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3043","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/95472"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3043"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3043\/revisions"}],"predecessor-version":[{"id":41884,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3043\/revisions\/41884"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3043"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3043"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3043"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3043"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}