1

In C#, it's possible to create a strictly sealed set of classes that inherit from a base that cannot be further extended like so:

public abstract record MyBase
{
    public sealed record A: MyBase;
    public sealed record B: MyBase;
    public sealed record C: MyBase;

    private MyBase() { }

    // My base props
}

MyBase can't be extended (by non-nested classes) because of the private constructor, and the other nested types can't be extended because they're sealed.

This allows you to use the type system to dictate control decisions with the confidence that some cowboy isn't going to come along and add a subclass that breaks everything.

It almost feels similar to rust's enums.

This has proven very useful in my current workflow, but is there a name for this pattern?

9
  • 3
    Why would this be a pattern rather than the application of two intentional language features?
    – Flater
    Jul 3, 2023 at 23:04
  • 1
    @Flater - A pattern is the application of several intentional language features... Jul 4, 2023 at 8:55
  • 1
    patterns tend to get named when they are used for something. Perhaps if you tell us what you found this pattern useful for?
    – Ewan
    Jul 4, 2023 at 20:14
  • @Ewan - So my actual class represents some email settings (to, from, replyto, subject, template etc.). I'm using the derived types to represent what type of email (and therefore what settings) are being used. So A could be ConfirmationEmail and B could be PasswordReset. This is in lieu of putting an EmailType enum and just having the one class. So what I've essentially created (at least I think so) is an enum with associated data. Jul 4, 2023 at 20:51
  • 2
    Being only slightly cheeky, I would say the design pattern here is the emulation of features or concepts for which the C# language has no manifest support. Here, discriminated unions. Jul 5, 2023 at 11:24

2 Answers 2

3

I don't know about a pattern, but it looks like you're trying to implement an algebraic data type (to be precise, a sum type). These are very popular particularly in functional languages, which will often have first-order support for them in terms of syntax, pattern matching and compiler exhaustiveness checking. The fact that C# doesn't have first-order support for them means you have to describe them in a slightly roundabout way (via abstract class + private constructor), won't get all the benefits, and using them may not be entirely idiomatic in the language.

The reason I say I'm not sure about calling this a pattern is that in languages that have this, it's just a normal language feature. Calling it a pattern would feel a little like calling inheritance from an interface a pattern in C#.

1
0

I'm not sure this counts as a pattern per se, but it looks like an implementation of an Enum class which is a way of having java-like enums in languages that don't directly support them (like C#.)

Depending on how you use this class, a possible pattern would be the strategy pattern. As an Example:

Public class ThingDoer 
{

  public OtherClass Foo;
  public void DoTheThing(MyBase strategy)
  {
     //common stuff to do before doing the thing...
     strategy.DoTheThing(this.Foo);
     // maybe some more stuff...    
  }
}
//and then later...
MyBase leetStrat = new MyBase.A();
MyFoo = MyDoer.DoTheThing(leetStrat); 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.