# C# Member Design Standards · CS-03

## Standard Metadata

- Area: C#
- Owner: Backend Steering group
- Last reviewed: 2026-09-09
- Next review due from: 2026-12-01
- Enforcement: CodeAnalysis / Rosyln Analyser / code review
- Status: Active

## Allow properties to be set in any order · CS-03.1 · **MUST**

Properties should be stateless with respect to other properties, i.e. there should not be a difference between first setting property `A` and then `B` or vice versa.

---

## Use a method instead of a property · CS-03.2 · **MUST**

Using a method is generally preferable to a property if:

* The work is more expensive than setting a field value;
* it represents a conversion such as the `Object.ToString()` method;
* it returns a different result each time it is called, even if the arguments didn't change. For example, the `NewGuid()` method returns a different value each time it is called; or
* the operation causes a side effect such as changing some internal state not directly related the property (which violates the [Command Query Separation](http://martinfowler.com/bliki/CommandQuerySeparation.html)).

**EXCEPTION**:
Populating an internal cache or implementing [lazy-loading](http://www.martinfowler.com/eaaCatalog/lazyLoad.html) is a good exception.

---

## Don't use mutually exclusive properties · CS-03.3 · **MUST**

Having properties that cannot be used at the same time typically signals a type that is representing two conflicting concepts. Even though those concepts may share some of the behavior and state, they obviously have different rules that do not cooperate.

This violation is often seen in domain models and introduces all kinds of conditional logic related to those conflicting rules, causing a ripple effect that significantly worsens the maintenance burden.

---

## A method or property does only one thing · CS-03.4 · **MUST**

Based on [SRP][srp], a method **MUST** have a single responsibility.

**Roslyn Analyzer Rule [AV1115](https://github.com/bkoelman/CSharpGuidelinesAnalyzer/blob/master/docs/Overview.md#av1115-a-property-method-or-local-function-should-do-only-one-thing-)(partial)**

---

## Don't expose stateful objects through static members · CS-03.5 · **SHOULD**

A stateful object is an object that contains many properties and lots of behavior behind that. If you expose such an object through a static property or method of some other object, it will be very difficult to refactor or unit test a class that relies on such a stateful object. In general, introducing a construction like that is a great example of violating many of the guidelines of this document.

A classic example of this is the `HttpContext.Current` property, part of ASP.NET. Many see the `HttpContext` class as a source for a lot of ugly code. In fact, the testing guideline [Isolate the Ugly Stuff](http://msdn.microsoft.com/en-us/magazine/dd263069.aspx#id0070015) often refers to this class.

---

## Return an `IEnumerable<T>` or `ICollection<T>` instead of a concrete collection class · CS-03.6 · **SHOULD**

In general, you don't want callers to be able to change an internal collection, so don't return arrays, lists or other collection classes directly. Instead, return an `IEnumerable<T>`, or, if the caller must be able to determine the count, an `ICollection<T>`.

**Note**:
In .NET 4.5, you can also use `IReadOnlyCollection<T>`, `IReadOnlyList<T>` or `IReadOnlyDictionary<TKey, TValue>`.

**Roslyn Analyzer Rule [AV1130](https://github.com/bkoelman/CSharpGuidelinesAnalyzer/blob/master/docs/Overview.md#av1130-return-an-ienumerablet-or-icollectiont-instead-of-a-concrete-collection-class-)**

---

## Properties, methods and arguments representing strings or collections should never be `null` · CS-03.7 · **SHOULD**

Returning `null` can be unexpected by the caller. Always return an **empty collection** or an **empty string** instead of a `null` reference. This also prevents cluttering your code base with additional checks for `null`, or even worse, `String.IsNotNullOrEmpty()` or `String.IsNullOrWhiteSpace()`.

**Roslyn Analyzer Rule [AV1135](https://github.com/bkoelman/CSharpGuidelinesAnalyzer/blob/master/docs/Overview.md#av1135-properties-arguments-and-return-values-representing-strings-or-collections-should-never-be-null-)**

---

## Define parameters as specific as possible · CS-03.8 · **SHOULD**

If your member needs a specific piece of data, define parameters as specific as that and don't take a container object instead. For instance, consider a method that needs a connection string that is exposed through some central `IConfiguration` interface. Rather than taking a dependency on the entire configuration, just define a parameter for the connection string. This not only prevents unnecessary coupling, it also improved maintainability in a long run.

---

## Consider using domain-specific value types rather than primitives · CS-03.9 · **COULD**

Instead of using strings, integers and decimals for representing domain specific types such as an ISBN number, an email address or amount of money, consider created dedicated value objects that wrap both the data and the validation rules that apply to it. By doing this, you prevent ending up having multiple implementations of the same business rules, which both improves maintainability and prevents bugs.

---

## Use init-only setters for properties that should be immutable after initialization · CS-03.10 · **MUST**

Use `init`-only setters for properties that should be settable in constructors and object initializers, but read-only after that.

For example you might have a `ProductDto` record that has some mutable properties (such as `StockLevel` and `Price`) but other properties (such as `Name` and `Description`) that should be immutable after object initialization:
```csharp
public record ProductDto
{
    public string Name { get; init; }

    public string Description { get; init; }

    public decimal Price { get; set; }

    public int StockLevel { get; set; }
}
```

[srp]: https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html
