Creating Classes in VS.NET

I'm sitting here at work building an application using TDD (which by itself is another post, and may be coming later), and every time I start a new class for another piece of the puzzle, I'm hating on how I have put the keyword "sealed" class in my declaration. Now, this isn't a major issue, but it can be if you plan on releasing an API for customers to build against. What's my issue? Well, I'm wondering if the "sealed" and "notinheritable" keywords should be applied by default in Whidbey.

My proposition comes from the fact that it is good design practice to have your classes become "sealed" or "not inheritable", that way your users cannot accidently inherit and break changes with your API. In practice this is a big deal, and how often are you building an API, and you become lazy to allow the default attributes/keywords/accessors be applied to a API (classes specifically, making them public instead of private or internal/friend)? I'm almost betting very frequently.

I propose that in Whidbey, and future versions, that "sealed" or "not inheritable" be applied by default to all new class declarations created by the IDE. This way, you have to make an effort and think about what you're doing when removing this keyword, and hopefully make you think if you really need to do so. 

As of right now, I realize that this can be accomplished by editing the templates used somwhere deep within the directory structure of VS.NET, so please don't tell me I can do this now. What are you're thoughts, feelings, objections to this?

8 Comments

  • I'd far prefer an option in VS to modify my default code template - so I could specify things like my default imports, accessibility options etc...

  • Thats actually a far better idea, have an actual "template editor" available in the IDE. Heck they're giving us a ton of control with the keystrokes, layout, etc...why not this too :)

  • There was a big discussion about this on one of the MSFT blogs a while ago; don't remember who. People fiercely arguing both sides, as they tend to do. I'm in the sealed camp. People should only be able to extend classes that were designed with that in mind. I really doubt that anyone designs every one of their classes to be used by a subclass, so the default of non-sealed doesn't make sense to me. On a big project you wind up seeing the brittle base class probem, not necessarily because people are lazy, but because it's so easy.



    +1 for sealed.

  • As long as you don't have any virtual or protected members that why do you care if your types are subclassed? What harm can they do?

  • Eric Lippert had a few posts on sealed a while back, that's probably what you're thinking of.

  • Hey, why not just remove inheritence altogether?

  • I think in large part your concerns are mitigated by the fact that virtual members must be opted in to, versus being default.



    To accidentally "inherit and break changes with your API" presumably is more specifically a concern that, through polymorphism and the ability to override default behavior, other parts of your API reliant upon said extended classes might break?



    For instance,



    public class ImportantClass {

    public ImportantClass(StrategyClass sc) {

    this.sc = sc;

    }

    private StrategyClass sc;

    Int32 ComputeSomething() {

    return sc.GetState() + 10;

    }

    }



    public class StrategyClass {

    Random rand = new Random();

    virtual Int32 GetState() {

    return rand.Next();

    }

    }



    Now I "break" ImportantClass's relationship on StrategyClass by providing the following implementation, and supplying it to the ImportantClass constructor:



    public class MyStrategyClass : StrategyClass {

    override Int32 GetState() {

    throw new Exception("Ha ha, you are broken!");

    }

    }



    In this case, yes a sealed class would have worked, but better API design would have better prevented such a problem (namely, not creating GetState() as virtual!).



    In summary, the typical concern is not with interface extension, but rather simply the concern that one could substitute a new implementation that goes against the grain of its dependant's expectations.

  • Very Good! I like!

Comments have been disabled for this content.