Exception Handling
Software Development
Best Practices
Programming
C#

Best practices throwing exceptions from properties

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Properties look like fields to the caller, so developers expect them to be cheap, predictable, and unsurprising. That does not mean properties can never throw exceptions, but it does mean you should be more conservative about throwing from properties than from explicit methods.

When Throwing From a Property Is Reasonable

Setters often validate input, and throwing there is normal:

csharp
1public class Person
2{
3    private int _age;
4
5    public int Age
6    {
7        get => _age;
8        set
9        {
10            if (value < 0)
11                throw new ArgumentOutOfRangeException(nameof(value));
12
13            _age = value;
14        }
15    }
16}

This is a good use of exceptions because the caller attempted an invalid assignment.

Getters can also throw in some cases, but the bar should be higher. For example, if the object is in an invalid state and the property cannot return a meaningful value, throwing may be appropriate.

Why Getters Deserve Extra Care

A property getter is commonly expected to behave like a field read. If it performs heavy computation, network I/O, or stateful work that frequently fails, a method is usually a better API.

Compare these two designs:

csharp
public string ConnectionString => _config["ConnectionString"]
    ?? throw new InvalidOperationException("Missing configuration.");

versus

csharp
1public string LoadRemoteProfile()
2{
3    // expensive or failure-prone operation
4}

The first may be acceptable because it is still essentially reading configuration state. The second should be a method because the name signals work and possible failure.

Prefer Specific Exceptions and Clear Contracts

If a property does throw, use the most specific exception you can and make the contract understandable.

Examples:

  • 'ArgumentOutOfRangeException in a setter'
  • 'InvalidOperationException when object state makes the property unavailable'
  • 'ObjectDisposedException when the object has already been disposed'

Avoid vague exceptions that force callers to guess what went wrong.

Make Common Access Cheap and Safe

A good rule is that normal property access should succeed in normal object state. If callers must routinely wrap a property read in try/catch, the API probably wants redesign.

Sometimes a better alternative is:

  • expose a method instead of a property
  • provide a TryGet... pattern
  • expose state through a nullable or optional value when absence is expected

That keeps exceptions reserved for exceptional situations instead of normal control flow.

Another good example is disposal-sensitive state:

csharp
1public Stream BaseStream
2{
3    get
4    {
5        if (_disposed)
6            throw new ObjectDisposedException(nameof(MyReader));
7
8        return _stream;
9    }
10}

This kind of getter exception is understandable because the object can no longer fulfill the contract after disposal. The property remains field-like, but object state makes access invalid anyway.

Common Pitfalls

One common mistake is hiding expensive or failure-prone operations behind a property getter. Callers read obj.Value very differently from obj.LoadValue().

Another issue is throwing broad exceptions from setters without naming the invalid argument or state clearly. Setters are often where precise exception types matter most.

It is also easy to overcorrect and claim properties should never throw. They can throw when object state or input is invalid, but the throwing behavior should still align with field-like expectations.

Summary

  • Property setters can reasonably throw when assigned values are invalid.
  • Property getters should stay cheap, predictable, and field-like whenever possible.
  • If reading a value involves heavy work or expected failure, prefer a method over a property.
  • Use specific exception types that match the actual error condition.
  • Design properties so normal reads succeed in normal object state without routine exception handling.

Course illustration
Course illustration

All Rights Reserved.