#1,164 – A Sealed Event Cannot Be Overridden

As with a method, you can use the sealed keyword when overriding a virtual event to indicate that child classes cannot override the event being defined.

When you override an event, you create a virtual event that behaves polymorphically.  The base class defines the event using the virtual keyword and you define the event in your child class using the override keyword.

When you use the override keyword, your event can itself be overridden in a child class.

If you want to override an event, but prevent any derived classes from overriding your implementation, you can use the sealed keyword to indicate that a child class must use the new keyword, rather than overriding your event.

    public class Dog
    {
        public string Name { get; set; }

        public Dog(string name)
        {
            Name = name;
        }

        public virtual event EventHandler<string> Barked;
    }

    public class Terrier : Dog
    {
        public Terrier(string name) : base(name) { }

        private EventHandler<string> terrierBarked;
        public sealed override event EventHandler<string> Barked
        {
            add
            {
                terrierBarked += value;
                // Special Terrier.Barked event logic here
            }
            remove
            {
                terrierBarked -= value;
            }
        }
    }

    public class JackRussell : Terrier
    {
        public JackRussell(string name) : base(name) { }

        public new event EventHandler<string> Barked;
    }
Advertisement

#767 – A struct Is Implicitly Sealed

Every struct in C#, whether it is user-defined or defined in the .NET Framework, is sealed–meaning that you can’t inherit from it.  A struct is sealed because it is a value type and all value types are sealed.

A struct can implement an interface, so it’s possible to see another type name following a colon, after the name of the struct.

In the example below, we get a compile-time error when we try to define a new struct that inherits from the one defined above.

    public struct PersonName
    {
        public PersonName(string first, string last)
        {
            First = first;
            Last = last;
        }

        public string First;
        public string Last;
    }

    // Error at compile time: Type 'PersonName' in interface list is not an interface
    public struct AngryPersonName : PersonName
    {
        public string AngryNickname;
    }

#678 – A Sealed Method Cannot Be Overridden

When you override a method, you create a virtual method that behaves polymorphically.  The base class defines the method using the virtual keyword and you define the method in your child class using the override keyword.

When you use the override keyword, your method can itself be overridden in a child class.

If you want to override a method in a base class, but also prevent any derived classes from overriding your method, you can use the sealed keyword to indicate that a child class must use the new keyword, rather than overriding your method.

    public class Dog
    {
        public virtual void Bark()
        {
            Console.WriteLine("  Dog.Bark");
        }
    }

    public class Terrier : Dog
    {
        public sealed override void Bark()
        {
            Console.WriteLine("  Terrier is barking");
        }
    }

    public class JRT : Terrier
    {
        public new void Bark()
        {
            Console.WriteLine("  JRT is barking");
        }
    }

#622 – Sealing vs. Not Sealing

There are two schools of thought when it comes to sealing a class to prevent inheritance:

  • Seal every class, unless you want the class to be inherited from and you plan for inheritance
  • Never seal a class, unless you specifically need to prevent other classes from inheriting from it

The people who argue for sealing classes by default argue that making inheritance work properly is tricky.  So if you haven’t specifically designed a class for inheritance (e.g. making certain methods virtual), you should prevent inheritance by sealing the class.

People who argue for not sealing a class by default will argue that you never know how someone might make use of your classes and it’s best to at least give them ability to try inheriting from your class.  The inheriting class can then deal with any issues that come up.

#621 – Sealing a Class to Prevent Inheritance

By default, a public class may be inherited from–by a class within the same assembly or even by a class in a different assembly.

To prevent your class from being used as a parent class, you can declare the class with the sealed keyword.  This “seals” the class, so that no one else can inherit from it.

    public sealed class Dog
    {
        public void Bark()
        {
            Console.WriteLine("Dog barking: Woof");
        }
    }

    // Compile-time error: Cannot derive from sealed type DogLibrary.Dog
    public class Terrier : Dog
    {
    }

A sealed class can’t be abstract–since the whole idea of an abstract class is that it is meant to serve as a base class for other classes.