views:

641

answers:

5

When is it appropriate to throw an exception from within a property getter or setter? When is it not appropriate? Why? Links to external documents on the subject would be helpful... Google turned up surprisingly little.

A: 

MSDN: Catching and Throwing Standard Exception Types

http://msdn.microsoft.com/en-us/library/ms229007.aspx

smack0007
+19  A: 

Microsoft has it's recommendations on how to design properties at http://msdn.microsoft.com/en-us/library/ms229006.aspx

Essentially, they recommend that property getters be lightweight accessors that are always safe to call. They recommend redesigning getters to be methods if exceptions are something you need to throw. For setters they indicate that exceptions are an appropriate and acceptable error handling strategy.

For indexers, Microsoft indicates that it is acceptable for both getters and setters to throw exceptions. And in fact, many indexers in the .NET library do this in fact. The most common exception being ArgumentOutOfRangeException.

There are some pretty good reasons why you don't want to throw exceptions in property getters:

  • Because properties "appear" to be fields, it is not always apparent that they can thrown a (by-design) exception; whereas with methods programmers are trained to expect and investigate whether exceptions are an expected consequence of invoking the method.
  • Getters are used by a lot of .NET infrastructure, like serializers and databinding (in WinForms and WPF for example) - dealing with exceptions in such contexts can rapidly become problematic.
  • Property getters are automatically evaluated by debuggers when you watch or inspect an object. Exception here can be confusing and slow down your debugging efforts. It's also undesirable to perform other expensive operations in properties (like accessing a database) for the same reasons.
  • Properties are often used in a chaining convention: obj.PropA.AnotherProp.YetAnother - with this kind of syntax it becomes problematic to decide where to inject exception catch statements.

As an aside, one should be aware that just because a property is not designed to throw an exception, that doesn't mean it won't .. it could easily be calling code that does. Even the simple act of allocating a new object (like a string) could result in exceptions. You should always write your code defensively and expect exceptions from anything you invoke.

LBushkin
This isn't to say that exceptions won't ever be thrown, though. Consider that any Get property that allocates JIT has the potential to throw due to the constructor. Would code really be better if it caught that exception silently?
Steven Sudit
If you're running into a fatal exception like "out of memory", it hardly matters whether you get the exception in a property or somewhere else. If you didn't get it in the property, you'd just get it a couple nanoseconds later from the next thing that allocates memory. The question isn't "can a property throw an exception?" Almost all code can throw an exception due to a fatal condition. The question is whether a property should *by design* throw an exception as part of its specific contract.
Eric Lippert
I'm not sure I understand the argument in this answer. For xample, regarding databinding - both WinForms and WPF are _specifically_ written to properly handle exceptions thrown by properties, and to treat them as validation failures - which is a perfectly fine (some even believe it to be the best) way to provide domain model validation.
Pavel Minaev
@Pavel - while both WinForms and WPF can gracefully recover from exceptions in property accessors, it is not always easy to identify and recover from such errors. In certain cases, (such as when in WPF a Control Template setter throws an exception) the exception is silently swallowed. This can lead to painful debugging sessions if you've never run across such cases before.
LBushkin
@Eric: If I understand what you're saying, then I agree. I'm not sure about the edge cases, though. For example, at one point I coded a class whose static constructor read some settings from a file, which would then be available as static Get properties. If it threw in that constructor, I caught it and set an invalid flag, so that every attempt to read a property would then throw an exception. Do you think that was a bad idea?
Steven Sudit
@Steven: Then how much use was that class to you in the exceptional case? If you've then had to write defensive code to handle all those exceptions because of one failure, and presumably supply suitable defaults, why not provide those defaults in your catch? Alternatively if the property exceptions are thrown to the user why not just throw the original "InvalidArgumentException" or similar so they could supply the missing settings file?
Zhaph - Ben Duguid
There's a reason why these are guidelines and not rules; no guideline covers all the crazy edge cases. I probably would have made these methods and not properties myself, but it's a judgement call.
Eric Lippert
@Zhaph: If the static constructor failed, that class would have been utterly useless, which is why I made the properties throw on get. I could not throw the original exception because there's no handy way to clone it, but I did log that exception and mention the log in the message.@Eric: Fair enough; I can certainly understand why that would make sense.
Steven Sudit
+9  A: 

It is almost never appropriate on a getter, and sometimes appropriate on a setter.

The best resource for these sorts of questions is "Framework Design Guidelines" by Cwalina and Abrams; it's available as a bound book, and large portions of it are also available online.

From section 5.2: Property Design

AVOID throwing exceptions from property getters. Property getters should be simple operations and should not have preconditions. If a getter can throw an exception, it should probably be redesigned to be a method. Note that this rule does not apply to indexers, where we do expect exceptions as a result of validating the arguments.

Note that this guideline only applies to property getters. It is OK to throw an exception in a property setter.

Eric Lippert
While (in general) I agree with such guidelines, it think it's useful to provide some additional insight as to why they should be followed - and what kind of consequences can arise when they are ignored.
LBushkin
How does this relate to disposable objects and the guidance that you should consider throwing `ObjectDisposedException` once the object has had `Dispose()` called and something subsequently asks for a property value? It seems like the guidance should be "avoid throwing exceptions from property getters, unless the object has been disposed in which case you should consider throwing an ObjectDisposedExcpetion".
Scott Dorman
Design is the art and science of finding reasonable compromises in the face of conflicting requirements. Either way seems like a reasonable compromise; I would not be surprised to have a disposed object throw on a property; nor would I be surprised if it did not. Since using a disposed object is a terrible programming practice, it would be unwise to have any expectations.
Eric Lippert
Another scenario where it's totally valid to throw exceptions from within getters is when an object is making use of class invariants to validate its internal state, which need to be checked whenever a public access is made, no matter it's a method or a property
Trap
+1  A: 

This is all documented in MSDN (as linked to in other answers) but here is a general rule of thumb...

In the setter, if your property should be validated above and beyond type. For example, a property called PhoneNumber should probably have regex validation and should throw an error if the format is not valid.

For getters, possibly when the value is null, but most likely that is something you will want to handle on the calling code (per the design guidelines).

David Stratton
+5  A: 

There's nothing wrong with throwing exceptions from setters. After all, what better way to indicate that the value is not valid for a given property?

For getters, it is generally frowned upon, and that can be explained pretty easily: a property getter, in general, reports the current state of an object; thus, the only case where it is reasonable for a getter to throw is when the state is invalid. But it is also generally considered to be a good idea to design your classes such that it is simply not possible to get an invalid object initially, or to put it into invalid state via normal means (i.e., always ensure full initialization in constructors, and try make methods exception-safe with respect to state validity and class invariants). So long as you stick to that rule, your property getters should never get into a situation where they have to report invalid state, and thus never throw.

There is one exception I know of, and it's actually a rather major one: any object implementing IDisposable. Dispose is specifically intended as a way to bring object into an invalid state, and there's even a special exception class, ObjectDisposedException, to be used in that case. It is perfectly normal to throw ObjectDisposedException from any class member, including property getters (and excluding Dispose itself), after the object has been disposed.

Pavel Minaev
Thanks Pavel. This answer goes in to 'why' instead of simply stating again that it's not a good idea to throw an exception from the properties.
SolutionYogi