As MonoGame.Extended evolves, we need consistent coding conventions to ensure maintainability and readability. This document outlines the standards expected to be followed when contributing to MonoGame.Extended.
These guidelines follow the general principle of "use Visual Studio defaults" and align with standard .NET coding conventions while addressing specific needs of the MonoGame.Extended library.
Braces: Use Allman style braces, where each brace begins on a new line.
Indentation: Use four spaces of indentation (no tabs).
Single-line Statements: All if/else if/else blocks should always use braces, even for single statements. This maintains consistency across the codebase.
// correct
if (foo == true)
{
DoSomething();
}
// incorrect
if (foo == true)
DoSomething();
Line Spacing: Avoid more than one empty line at any time. Do not have two blank lines between members of a type.
White Space: Avoid spurious free spaces (e.g., avoid if (someVar == 0)...).
This Keyword: Avoid this. unless absolutely necessary.
HslColor, ParticleEmitter)IGameComponent, IUpdateable)BlendMode.Additive)TKey, TValue)Update(), Draw())Position, Rotation)_camelCase for internal and private instance fields (e.g., _particles, _isActive)s_ (e.g., s_defaultSize)t_ (e.g., t_instance)readonly where possible (after static when used together)MAX_PARTICLES, DEFAULT_DURATION)CollisionEventHandler)Preferred Approach for MonoGame.Extended Types:
When Extension Methods Are Necessary:
{TypeName}Extensions (e.g., ColorExtensions, Vector2Extensions)From{SourceType} for static factory methods on the target typeTargetType.FromSourceType(source) creates a TargetType from a SourceTypeTo{TargetType} for extension methods on the source typesource.ToTargetType() as an extension method on SourceType returns a TargetType{SourceType}To{TargetType} naming for conversion methodsConversionHelper.SourceTypeToTargetType(source){Domain}Helper (e.g., ColorHelper, MathHelper)Visibility: Always specify visibility, even if it's the default (e.g., private string _foo not string _foo).
public abstract not abstract public).Namespace Imports:
namespace declarationsSystem.* namespacesMicrosoft.Xna.Framework.*Example:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using MonoGame.Extended.Graphics;
using MonoGame.Extended.Particles;
Type References:
int, string, float instead of Int32, String, Single)int.Parse instead of Int32.Parse)Variable Declarations:
var. C# is a strongly typed language, and using explicit types improves code readability.var only when absolutely necessary, not as a general practice.new() can only be used when the type is explicitly named on the left-hand side (e.g., SourceType source = new())String References: Use nameof(...) instead of "..." whenever possible and relevant.
MonoGame.Extended.Graphics (corresponding to MonoGame's Microsoft.Xna.Framework.Graphics)MonoGame.Extended.Input (corresponding to MonoGame's Microsoft.Xna.Framework.Input)MonoGame.Extended directly (corresponding to MonoGame's Microsoft.Xna.Framework)MonoGame.Extended.Audio (corresponding to MonoGame's Microsoft.Xna.Framework.Audio)MonoGame.Extended for fundamental extensions and typesMonoGame.Extended.{Domain} for features that extend beyond MonoGame's core
MonoGame.Extended.ParticlesMonoGame.Extended.Tiled<param> tags<returns> tags<exception> tagsArgumentNullException.ThrowIfNull and similar methods where available.// CORRECT: Dedicated extension class for Foo
public static class FooExtensions
{
public static Bar ToBar(this Foo foo)
{
// Implementation
}
}
// CORRECT: Dedicated extension class for Bar
public static class BarExtensions
{
public static Foo ToFoo(this Bar bar)
{
// Implementation
}
}
// CORRECT: Factory method on target type
public struct TargetType
{
public static TargetType FromSourceType(SourceType source)
{
// Implementation
}
}
// CORRECT: Extension method on source type
public static class SourceTypeExtensions
{
public static TargetType ToTargetType(this SourceType source)
{
// Implementation
}
}
// CORRECT: Helper class method naming
public static class ConversionHelper
{
public static TargetType SourceTypeToTargetType(SourceType source)
{
// Implementation
}
public static SourceType TargetTypeToSourceType(TargetType target)
{
// Implementation
}
}
Below is an example following our style guidelines:
ExampleClass.cs:
using System;
using System.Collections.Generic;
namespace Example
{
public partial class ExampleClass
{
private readonly List<Item> _items;
private float _rate;
public int Count
{
get { return _items.Count; }
}
public bool IsEnabled { get; private set; }
public ExampleClass(int capacity)
{
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(capacity);
_items = new List<Item>(capacity);
IsEnabled = true;
}
public void Update(GameTime gameTime)
{
if (!IsEnabled)
{
return;
}
UpdateItems();
CreateItems();
}
private void UpdateItems(GameTime gameTime)
{
// Implementation
}
private void CreateItems(GameTime gameTime)
{
// Implementation
}
}
}