My CS program taught .NET almost entirely in the context of enterprise Windows apps, so I never touched the cross-platform side. Here's what I found once I actually tried it.
The assumption I had
I figured "cross-platform .NET" meant technically possible but painful in practice — the kind of thing where you spend more time fighting platform quirks than writing actual features.
What actually happened
I set up a small project targeting both a web API and a console tool meant to run on my Linux machine, using the same C# codebase and most of the same libraries. The setup itself was straightforward — install the SDK, dotnet new, and it just ran on Linux without extra configuration for basic cases.
Where it got real was dependency management: not every NuGet package plays equally well across platforms, so a couple of libraries I initially reached for out of habit needed swapping for cross-platform-friendly alternatives. Nothing broken, just a reminder to check before committing to a package.
What surprised me
The tooling experience (debugging, hot reload, project structure) felt basically identical whether I was on Windows or Linux. I expected a noticeably "second-class" experience outside Windows and didn't really get one.
Where I'd still be cautious
If your project leans heavily on Windows-specific APIs (certain UI frameworks, some legacy interop), cross-platform isn't automatic — you're still choosing the right project type (e.g. MAUI for cross-platform UI vs. WPF, which stays Windows-only). It's not "write anything, run anywhere" by default; it's "the option exists if you plan for it."
Worth trying if:
- You're comfortable in C# already and want to build something outside a Windows-only assumption
- You want one language across web, backend, and eventually mobile/desktop instead of learning a separate stack for each
Docs and downloads here if you want to try the setup yourself: https://dotnet.microsoft.com/?wt.mc_id=studentamb_503800
Curious if anyone's hit real platform-specific pain points going further than a small test project — genuinely want to know what breaks at scale.
Top comments (4)
That “plan for it” qualifier is where cross-platform reliability really starts. The managed API surface can compile everywhere while a package still carries RID-specific native assets, and Linux will expose assumptions Windows hides—case-sensitive paths and ICU/culture behavior are common examples. My minimum guardrail is a Linux CI job that restores, publishes for the same RID or container used in production, and runs integration tests there; a Windows-only build is not equivalent evidence. When evaluating a NuGet dependency, I’d inspect its
runtimes/assets and test one representative culture and file path before it becomes architectural glue. Which dependency forced your first swap: a managed API mismatch or a native runtime asset?Native runtime asset, for me — System.Drawing.Common. Worked fine locally on Windows since it’s just wrapping GDI+, but it throws PlatformNotSupportedException on Linux from .NET 6 onward (Microsoft made that explicit rather than letting it silently degrade, which I appreciated in hindsight). Swapped to SixLabors.ImageSharp, which is fully managed and doesn’t care about the runtimes/ folder at all.
Good callout on the CI point too — I was testing cross-platform behavior locally in a container rather than in an actual pipeline, which caught the Linux failure but wouldn’t have caught culture/locale issues the way a proper CI job would. Adding that as a next step before I’d trust this beyond a toy project.
🤝🤝
That’s exactly the kind of example I had in mind. System.Drawing.Common is almost a textbook case of the .NET runtime being cross-platform while a familiar dependency is not. Moving to ImageSharp removes that Windows-specific boundary, and promoting your container check into Linux CI should keep it visible as the project grows. It’s also worth watching
CA1416, which can catch platform-specific API calls at build time. Thanks for sharing the concrete package and migration path.