Personix.CodeStyle 1.1.0

dotnet add package Personix.CodeStyle --version 1.1.0
                    
NuGet\Install-Package Personix.CodeStyle -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Personix.CodeStyle" Version="1.1.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Personix.CodeStyle" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Personix.CodeStyle">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Personix.CodeStyle --version 1.1.0
                    
#r "nuget: Personix.CodeStyle, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Personix.CodeStyle@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Personix.CodeStyle&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Personix.CodeStyle&version=1.1.0
                    
Install as a Cake Tool

Personix.CodeStyle

Shared code style rules for Personix .NET projects, delivered as a global AnalyzerConfig.

Referencing this package turns the agreed rules into build errors, so they hold in CI and on every machine — instead of depending on whether each developer happens to have the same editor settings. Changing a rule means bumping one package version, not editing nine repositories.

Installation

<PackageReference Include="Personix.CodeStyle" Version="1.1.0" PrivateAssets="all" />

PrivateAssets="all" keeps the rules from flowing to consumers of your package — they govern your build, not theirs. Put the reference in Directory.Build.props to cover every project in a repository at once.

What it enforces

Rule Severity Meaning
IDE0011 error Braces on every control-flow statement, including single-line if.
IDE0161 warning File-scoped namespace declarations.
IDE0005 warning No unused using directives.
IDE0051 / IDE0052 warning No unread private members.
IDE0060 suggestion Unused parameters.
IDE1006 warning Private field naming: _underscore on instance fields, PascalCase on const and static readonly ones.
IDE0022 silent Block bodies for methods — a rule for what the IDE generates, not for what is already written.
PERSONIX005 warning A setter used only while the object is being created should be init.
PERSONIX006 warning An init property without a default that every creation site sets should be required.

Braces are an error rather than a warning on purpose: the failure mode is a second statement added under an unbraced if, which silently falls outside the condition and reads as if it did not.

IDE0022 is silent for the opposite reason. It exists so that implementing an interface or base member produces a method with a body to fill in rather than an expression to unwrap first. Whether a finished method reads better as one or the other is a judgement per method, so nothing is underlined and code cleanup leaves settled code alone.

Alongside the analyzer rules, the package fails the build on a handful of conventions that no analyzer covers. All of them are errors, because each describes something that is either agreed or not — there is no useful middle setting.

Rule Applies to Meaning
PERSONIX001 packable projects A published package must carry docs/README.md. The package is wired up as the NuGet readme automatically, so no csproj needs to set PackageReadmeFile.
PERSONIX002 test projects FluentAssertions, AwesomeAssertions and NFluent are refused. FluentAssertions is commercially licensed from version 8.
PERSONIX003 every project NSubstitute and FakeItEasy are refused. Moq is the test double library across Personix.
PERSONIX004 test projects A test project must reference Shouldly. Banning the alternatives is not the same as having the agreed one.

PERSONIX003 deliberately ignores IsTestProject. Scoping it to test projects would leave the rule silent exactly where an unwanted reference is least likely to be noticed — a helper or fixture project that never set the flag.

PERSONIX005

A property with a set accessor is reported when every write to it in the project happens while the object is being created: in an object initializer, in a with expression, or in a constructor of the declaring or a derived type. Changing set to init then compiles unchanged and states what the code already relies on.

Any other write keeps the property quiet — an assignment after construction, a compound assignment, ++, ??=, deconstruction, a write inside a lambda, or a nested initializer such as new Team { Lead = { Name = "Ann" } }. So does a setter that nothing in the project writes, since such a property is usually filled by a serializer or a binder.

PERSONIX006

An init property is reported when it has no default value, no constructor assigns it, and every new of its type in the project sets it. Adding required then compiles unchanged and makes the compiler hold the next creation site to the same rule. A with expression is not a creation site, and creating a derived type counts as creating the base type.

System.Text.Json honours required: after the change, deserializing JSON that lacks the property throws instead of leaving the default. Check that before adding the modifier to a type that is also read from JSON.

Scope of both rules

The analyzer sees one project at a time. Neither rule applies to static, abstract, virtual or overriding properties, to interface implementations, or to positional record parameters.

In a packable project, a property whose setter is visible outside the assembly is skipped, because consumers of the package may write it. A project that is not packable has no such consumers, so its public properties are analysed as well.

That leaves one blind spot in layered solutions. A type declared in one project and created or mutated in another is judged only by what its own project does with it. A Domain type that Infrastructure creates is never reported under PERSONIX006, and a Domain property that Application mutates can be reported under PERSONIX005 even though the change would not compile. In that case, suppress the diagnostic on the property with [SuppressMessage("Design", "PERSONIX005")].

What it does not cover

Formatting that the editor applies as you type — indentation, encoding, line endings — comes from .editorconfig, which MSBuild reads from disk and cannot be delivered in a package. Keep a small .editorconfig in each repository for that. It changes rarely; this package holds the rules that actually change.

Overriding a rule

A repository-local .editorconfig takes precedence over this global config, so a project with a genuine reason can relax a specific rule locally. That is intended — the package sets the default, not an absolute.

Licence

MIT — see LICENSE.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 0 9/22/2026
1.0.5 104 9/11/2026
1.0.4 126 8/31/2026
1.0.3 186 8/27/2026
1.0.2 139 8/27/2026
1.0.1 147 8/18/2026
1.0.0 197 8/1/2026

1.1.0 — adds an analyzer with PERSONIX005 (setter used only during object creation should be init) and PERSONIX006 (init property set at every creation should be required). 1.0.5 — Release notes brought up to date, no rule changes. 1.0.4 made IDE0022 give generated methods a block body instead of an expression body. 1.0.3 added IDE1006 naming rules for private fields.