Brad Abrams (MS) has put up another one of his classes on framework design/implementation considerations. In this one he goes into the correct usage of constructors, methods, properties, fields and events.
To save you the time of watching it, or reading the transcript, I've tried to summarize what he said here:
1. Constructors should contain minimal functionality. Just capture the data passed in and be done. Some choose to do lots of work in the constructor to make other operations on the class faster. The problem here is that often you won't use the class at all, and the processing will be wasted.
2. It's ok to throw exceptions in the constructor.
3. Always add a default constructor to avoid versioning issues. Adding another constructor will remove the implicit default constructor, so it's best to add the default constructor explicitly up-front.
4. Provide property alternatives to large constructors. As well as providing parameterized constructors, also provide default constructors with configuration options via properties. Try to use the "drag and drop" metaphor - where you construct the object (drop it on a form) and then set properties later, rather than forcing the developer to set the properties when constructing the object.
5. Ensure methods with the same name do exactly the same thing. When overloading, do not change the behavior of the function with each overload. Name the parameters consistently between overloads. If overloading is used to offer optional parameters, the overload should be doing nothing extra other than providing a default value for the missing parameter.
6. There's no reason to make all overloads virtual, just make the most complex overload virtual, as the others should default. The exception is if you want to override the defaults for missing parameters.
7. To help the JITter inline code (for performance): minimize virtual declarations, minimize size of methods and minimize the number of local declarations you have. All of these can stop the just-in-time compiler from optimizing your code.
8. Avoid publicly exposed fields from framework classes. You give up so much control and versioning, it's much easier in the long run to use properties.
9. When defining properties, don't create write-only properties and consider using PropertyChanged events when the properties are on controls.
10. Keep property getters simple. They shouldn't throw exceptions, as this can cause problems in debuggers. If they actually perform some work and/or change the state of the class, it should be a method and not a property getter.
11. Properties should be independent of one another. You should be able to set properties in any order. If a specific order is required, use a method.
12. Avoid properties that return arrays, instead use a method. You shouldn't be providing direct access to internal arrays in your class, so your property should be copying the array. Because it's doing work, it should be a method instead.
13. Use indexers (eg. this[]) if the backing storage for the class is a collection. Keep the indexer itself simple - string or int parameters.
14. Name events with a verb. eg. Click, Paint, DrawItem, DropDown.
15. Events should return void. They should follow the signature of sender, event-arguments.
16. Keep event argument parameters as strongly typed.
17. Put a try/finally around where you're raising an event because the handler could throw an exception.
18. Use statics where the method can be invoked indepdently of the class instance, and where instantiation is overkill. eg. Math. When creating singletons use static readonly.
19. Avoid using ref to return multiple parameters. Instead put the values into a struct and return the struct. When using 'out' in C# parameters, consider the fact that 'out' is not supported in the CLR and ends up being translated to a 'ref' parameter anyway, so the out semantics cannot always be enforced.
20. Always validate arguments passed into public methods. When validating arguments to public methods, throw exceptions derived from ArgumentException.