Identifying and Removing Unused NuGet Packages in Solutions: Methods and Tools

Dec 08, 2025 · Programming · 11 views · 7.8

Keywords: NuGet package management | unused package detection | Visual Studio tools

Abstract: This article provides an in-depth exploration of techniques for identifying and removing unused NuGet packages in Visual Studio solutions. Focusing on ReSharper 2016.1's functionality, it details the mechanism of detecting unused packages through code analysis and building a NuGet usage graph, while noting limitations for project.json and ASP.NET Core projects. Additionally, it supplements with Visual Studio 2019's built-in remove unused references feature, the ResolveUR extension, and ReSharper 2019.1.1 alternatives, offering comprehensive practical guidance. By comparing the pros and cons of different tools, it helps developers make informed choices in maintaining project dependencies, ensuring codebase cleanliness and maintainability.

Introduction

In modern software development, the NuGet package manager has become an essential dependency management tool in the .NET ecosystem. As project scales grow, solutions may accumulate numerous installed NuGet packages, many of which may become unused due to code refactoring, feature removal, or initial configuration errors. These unused packages not only increase project complexity and build times but also pose risks from security vulnerabilities or compatibility issues. Therefore, regularly cleaning up unused NuGet packages is a critical practice for maintaining codebase health. This article systematically introduces methods for identifying and removing unused NuGet packages, with a focus on analyzing the working principles and applicable scenarios of mainstream tools.

ReSharper 2016.1's Unused Package Detection Feature

ReSharper 2016.1 introduced a dedicated feature for automatically detecting and suggesting the removal of unused NuGet packages in solutions. This feature is based on static code analysis technology and operates through the following three steps:

  1. Code Analysis and Assembly Reference Collection: ReSharper first scans all source code files in the project, parses the syntax trees, and identifies explicit and implicit references to assemblies. For example, in C# code, when using statements import namespaces or types are directly referenced, these references are recorded. Below is a simple code example illustrating how assembly dependencies can be identified by analyzing using directives:
// Example: Assembly references in code
using System;
using Newtonsoft.Json; // This implies a dependency on the Newtonsoft.Json assembly

public class Example
{
    public void ProcessData(string json)
    {
        var obj = JsonConvert.DeserializeObject<dynamic>(json); // Direct use of JsonConvert type
    }
}

In this example, ReSharper would detect the reference to the Newtonsoft.Json assembly and associate it with the corresponding NuGet package.

<ol start="2">
  • Building a NuGet Usage Graph: Based on the collected assembly references, ReSharper constructs a dependency graph where nodes represent NuGet packages and edges represent dependencies between packages. This graph includes not only directly referenced packages but also transitive dependencies. For instance, if a project references package A, and package A depends on package B, then package B is also included in the graph. By analyzing this graph, the tool can determine which packages are actually used in the code.
  • Identifying Unused Packages: ReSharper marks packages as unused if they have no content files, are not used themselves, and have no used dependencies. For example, suppose a solution has package UnusedPackage installed, but no types or functionalities it provides are ever referenced in the code, and no other used packages depend on it; then it would be suggested for removal. This approach helps reduce false positives, ensuring only truly redundant packages are removed.
  • However, this feature has some limitations. According to official documentation, it does not work for projects using project.json configuration (such as some older .NET Core projects) and ASP.NET Core projects. These limitations are primarily due to the different dependency management mechanisms in these project types compared to traditional .csproj files, making static analysis tools challenging to parse references accurately. Therefore, when using ReSharper for cleanup, developers need to verify project type compatibility.

    Visual Studio 2019's Built-in Feature

    Starting from Visual Studio 2019 version 16.9, Microsoft introduced a built-in remove unused references feature, providing convenience for developers not using ReSharper. To enable this feature, follow these steps: go to Tools > Options > Text Editor > C# > Advanced, and under the Analysis section, check "Show 'Remove Unused References' command". In version 16.10 and later, this feature is more intuitive: right-click on the project and select "Remove Unused References". This functionality analyzes references and code usage in project files to automatically identify unused NuGet packages and other references (e.g., DLL files), offering a one-click removal option. Similar to ReSharper, it is based on static analysis but may be more lightweight, suitable for integration into standard development workflows.

    Other Tools and Alternatives

    Beyond the mainstream tools, several other options are available for cleaning up unused NuGet packages:

    These tools have their pros and cons: ReSharper offers deep analysis but may have compatibility limitations; Visual Studio's built-in feature is easy to use but may not be as comprehensive as third-party tools; extensions like ResolveUR fill gaps for older versions. Developers should choose the appropriate tool based on project requirements, version compatibility, and personal preference.

    Practical Recommendations and Considerations

    When cleaning up unused NuGet packages, following best practices can avoid potential issues:

    1. Backup and Version Control: Before performing any cleanup, ensure the project is committed to a version control system (e.g., Git) or create a backup. This allows quick recovery if the tool mistakenly removes necessary packages.
    2. Incremental Validation: It is advisable to clean up packages project-by-project or package-by-package, rather than removing all unused ones at once. After each removal, run builds and tests to ensure no compilation errors or runtime issues are introduced. For example, some packages might be used via reflection or dynamic loading, which static analysis tools may not detect.
    3. Monitor Dependency Impact: When removing packages, note their transitive dependencies. If a package is removed, but other packages it depends on might still be in use, manually check to avoid breaking dependency chains. Tools like the dotnet list package command can help visualize package dependencies.
    4. Combine with Update Management: After cleaning unused packages, updating the remaining packages can be done more safely, reducing risks from compatibility issues. Regularly performing this process helps keep project dependencies tidy and up-to-date.

    By systematically applying these methods, developers can effectively optimize solutions, enhancing code quality and maintenance efficiency.

    Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.