Presumably this doesn't prevent a developer from creating another "pattern class" subclassing some superclass in another package, thereby breaking existing pattern matches?
Mark all your types sealed. Roslyn can have a custom diagnostic analyzer to yell about unsealed pattern-matched public classes, but I'm not sure if we want to add language support for a closed set yet.
Scala allows you to seal a type hierarchy to a single file. That would work, but it seems hacky -- a file feels more like an implementation detail than a language construct to me. For one, the C# spec doesn't mention files at all -- from its perspective all your code may as well be in one giant file.
C# doesn't allow you to specify both abstract and sealed on the same class - something that would be really useful for implementing closed types. The restriction is artificial and unnecessary though - CIL allows the two to coexist, and it is how the F# compiler implements discriminated unions. I think it would be wise to aim for feature-compatibility with F#, to ensure you can pattern match over types defined in F# from C#, and vice-versa.
Scala allows you to seal a type hierarchy to a single file. That would work, but it seems hacky -- a file feels more like an implementation detail than a language construct to me. For one, the C# spec doesn't mention files at all -- from its perspective all your code may as well be in one giant file.