icsharpcode/ILSpy · error · ArgumentNullException

typeSystem

Error message

typeSystem

What it means

Thrown by the CSharpDecompiler(IDecompilerTypeSystem, DecompilerSettings) constructor: this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem)). The message is the parameter name 'typeSystem'. The decompiler needs a fully built type system to operate.

Source

Thrown at ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs:375

		public CSharpDecompiler(string fileName, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
			: this(LoadPEFile(fileName, settings), assemblyResolver, settings)
		{
		}

		/// <summary>
		/// Creates a new <see cref="CSharpDecompiler"/> instance from the given <paramref name="module"/> using the given <paramref name="assemblyResolver"/> and <paramref name="settings"/>.
		/// </summary>
		public CSharpDecompiler(MetadataFile module, IAssemblyResolver assemblyResolver, DecompilerSettings settings)
			: this(new DecompilerTypeSystem(module, assemblyResolver, settings), settings)
		{
		}

		/// <summary>
		/// Creates a new <see cref="CSharpDecompiler"/> instance from the given <paramref name="typeSystem"/> and the given <paramref name="settings"/>.
		/// </summary>
		public CSharpDecompiler(IDecompilerTypeSystem typeSystem, DecompilerSettings settings)
		{
			this.typeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
			this.settings = settings;
			this.module = typeSystem.MainModule;
			this.metadata = module.MetadataFile.Metadata;
			if (module.TypeSystemOptions.HasFlag(TypeSystemOptions.Uncached))
				throw new ArgumentException("Cannot use an uncached type system in the decompiler.");
		}

		#region MemberIsHidden
		/// <summary>
		/// Determines whether a <paramref name="member"/> should be hidden from the decompiled code. This is used to exclude compiler-generated code that is handled by transforms from the output.
		/// </summary>
		/// <param name="module">The module containing the member.</param>
		/// <param name="member">The metadata token/handle of the member. Can be a TypeDef, MethodDef or FieldDef.</param>
		/// <param name="settings">The settings used to determine whether code should be hidden. E.g. if async methods are not transformed, async state machines are included in the decompiled code.</param>
		public static bool MemberIsHidden(MetadataFile? module, EntityHandle member, DecompilerSettings settings)
		{
			if (module == null || member.IsNil)
				return false;

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Build an IDecompilerTypeSystem first (e.g. new DecompilerTypeSystem(module, resolver, settings)) and pass it.
  2. Or use the CSharpDecompiler(MetadataFile, IAssemblyResolver, DecompilerSettings) overload, which builds the type system for you.
  3. Null-check the type system before constructing.

Example fix

// before
var decompiler = new CSharpDecompiler(null, settings);

// after
var ts = new DecompilerTypeSystem(module, resolver, settings);
var decompiler = new CSharpDecompiler(ts, settings);
// or simply:
// var decompiler = new CSharpDecompiler(module, resolver, settings);
Defensive patterns

Strategy: validation

Validate before calling

if (typeSystem == null) throw new ArgumentNullException(nameof(typeSystem));
var decompiler = new CSharpDecompiler(typeSystem, settings);

Try / catch

var decompiler = typeSystem != null
    ? new CSharpDecompiler(typeSystem, settings)
    : throw new ArgumentNullException(nameof(typeSystem));

Prevention

When it happens

Trigger: Constructing new CSharpDecompiler(null, settings), or a caller whose factory returned a null type system.

Common situations: Caller forgot to build a DecompilerTypeSystem; a DI/MEF composition that failed to provide the type system.

Related errors


AI-assisted analysis of icsharpcode/ILSpy@60c08fcb74 (2026-08-13). Data as JSON: /api/errors/ecf11c59a7e8dc15. Report an issue: GitHub.