Skip to content

Namespaces in C#

↑

A namespace gives related types a shared name and prevents unrelated classes from colliding. It is not a security boundary, a directory, or a compiled assembly. A using directive makes a namespace easier to refer to; it does not import source files into your program.

Imagine two packages defining a Logger class. Without an enclosing namespace, both classes would compete for the same type name. HCSTech.Logging.Logger and Vendor.Diagnostics.Logger can coexist because their fully qualified names differ. You choose which to refer to, either explicitly or through using.

C# | Logger.cs
namespace HCSTech.Logging;
public sealed class Logger
{
public void Write(string message) => Console.WriteLine(message);
}
// In a separate source file:
using HCSTech.Logging;
Logger logger = new();
logger.Write("Hello");
  1. Start with a stable root. For example, HCSTech.Gameplay or HCSTech.Tools. This reduces clashes with third-party packages.
  2. Group by responsibility. Prefer Gameplay.Inventory or Gameplay.Combat to namespaces named after arbitrary folder numbers.
  3. Keep public APIs understandable. Callers should be able to guess where a type belongs.
  4. Rename carefully. Moving a file does not require changing the namespace, but changing a namespace can break references and serialized type names.

namespace MyApp.Core; applies to the whole file and avoids another indentation level. The older block form namespace MyApp.Core { ... } is useful when a file intentionally contains more than one namespace, but that is uncommon. Choose one convention and enforce it consistently.

You can write using FileLogger = HCSTech.Logging.Logger; to give a type a local alias. If two imported namespaces contain the same class name, use a fully qualified name or an alias rather than relying on an ambiguous short name.

Namespaces help separate runtime gameplay code from editor tooling and third-party systems. Unity may serialize references to script types, so reorganizing namespaces in an existing project deserves testing. Namespaces by themselves do not improve compilation speed; assembly definitions create the relevant compilation boundaries.