How do you share code between projects/solutions in Visual Studio?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The most maintainable way to share code between Visual Studio projects is usually to move that code into a class library and reference it from the consuming projects. If the code must be reused across multiple solutions or teams, publishing that library as a NuGet package is often the next step up.
Start With a Class Library
For most .NET codebases, a class library is the default answer because it gives you:
- one compiled assembly
- one place for tests
- clear versioning boundaries
- explicit project references
Example layout:
MyApp.Shared contains reusable domain models, utility code, abstractions, or common services. The app projects reference it normally.
Example Project Reference
The shared project file might look like this:
And a consuming project references it like this:
Once referenced, the shared code is used like any other dependency:
When a Shared Project Makes Sense
Visual Studio also has Shared Projects, which include source files directly into each consuming project at compile time. That can be useful when:
- you need platform-specific conditional compilation
- you do not want a separate assembly
- you are working with multi-targeted application code that differs per platform
The tradeoff is that Shared Projects are less isolated. Because the source is compiled into each consumer, dependency boundaries are fuzzier and build behavior can vary between targets.
For ordinary business logic, a class library is usually cleaner.
Linked Files Are a Small-Scale Option
If you only need to share one or two files, Visual Studio lets you add an existing file "as link" so the same physical file appears in more than one project.
That can work for tiny cases, but it scales poorly. Shared files can quietly accumulate incompatible assumptions between projects, and refactoring becomes risky because there is no library boundary.
Sharing Across Multiple Solutions
If several solutions need the same code, a local project reference may no longer be enough. At that point, packaging the shared library as a NuGet package is usually the right move.
Basic flow:
Then consuming solutions reference the package version rather than a file path:
This is better for:
- independent release cycles
- multiple repositories
- CI and reproducible builds
- team-wide dependency management
Pick the Boundary Carefully
Not every utility method belongs in a shared library. Good shared code has a stable purpose and low coupling. Bad shared code becomes a dumping ground that every project depends on for unrelated reasons.
A useful rule is:
- share domain contracts, reusable services, or stable utility abstractions
- avoid stuffing app-specific logic into a "Common" project just because two callers currently need it
Common Pitfalls
The biggest mistake is using linked files or copy-pasted code when a real class library should exist. That usually creates drift, duplicate bug fixes, and confusing ownership.
Another issue is creating a giant "shared" assembly that knows too much about every application. That turns reuse into coupling. Developers also often choose Shared Projects when they really just need a normal library. Shared Projects are helpful for source sharing, but they are not the default best practice for ordinary .NET reuse.
Summary
- A class library is usually the best way to share code between Visual Studio projects.
- Use project references inside a solution for simple reuse.
- Use NuGet packages when the shared code must be reused across multiple solutions or repositories.
- Shared Projects and linked files exist, but they are more specialized tools.
- Design the shared boundary carefully so reuse does not become accidental coupling.

