
.NET development on Apple Silicon
TL;DR
Apple Silicon devices are great. My MacStudio is powerful, and I have difficulty using all the available resources. The machine, for most of the workloads, is simply outstanding. When it comes to .NET development, The scenario is twofold. On the one hand, there is .NET 6 (and onward) development which works excellently on macOS and Apple Silicon. I’m a JetBrains Rider user; however, both Visual Studio Code and Visual Studio for Mac work great.
On the other hand, there is .NET Framework development. It requires a virtual machine, and I have a Parallels one. The virtual machine OS must be ARM which poses a set of limitations to developers—most of the .NET development tools for Windows don’t play nicely with an ARM architecture. Currently, the best option is to use Visual Studio 2022 Preview 2 (and onward), which comes with ARM support, and update the target framework to .NET 4.8.1. If that’s not possible, get ready to spend time troubleshooting subtle errors.
I’ve used a Dell Precision Tower 5810 workstation (8 core Xeon, 32GB of RAM, and 1TB SSD) for the last seven years and Windows as my primary OS for most of my career. I had an experience with macOS for a couple of years around 2010.
I recently (April 2022) bought a MacStudio (M1 Ultra, 64GB of RAM, 1TB SSD).
This post intends to be a live-blogging thing, sharing my experience as a long-time Windows user and, more importantly, a .NET developer. I started with .NET development in 1999 with one of the first alpha releases.
Let’s get started 😬 pic.twitter.com/K55bOMQojn
— Mauro Servienti 🐙 (@mauroservienti) April 6, 2022
Before getting into the nitty-gritty details of .NET development using an M1 chip and macOS, let me give you an overview of the hardware. I’m famous among my friends and colleagues for my diplomacy.
The MacStudio built-in audio quality is shit. I had never heard something so utterly inadequate. I should have expected it. Apple, during the presentation, never mentioned the audio using their usual style, “The best XYZ feature of all times.” And so, there we go. Even for regular Zoom calls, you need external speakers or headphones.
Having a lot of thunderbolt ports, six on my model (four in the back and two on the front), is a huge bonus. Plugging in devices has never been so easy. Except if you want to plug in not-officially-supported USB-C screens.
I have two Dell 32” 4K screens (U3219Q) claiming to support DisplayPort over the USB-C connection. But things are not so easy. I’m not sure why, but it sounds like external screens and projectors are more or less always a source of pain with Apple machines.
The problem manifests itself at boot time. The screen is in standby mode, the machine starts, the screen wakes up and starts the USB-C handshaking process. But that happens too early, and the response from the Mac times out. The screen never retries and never connects. The “easy” workaround is disconnecting and reconnecting the USB-C cable, and the screen immediately starts working. However, if you’re using the screen as a USB hub, that causes a mess with USB devices connected to the screen. Dell forums are full of people complaining about this issue, so it’s not something new to the MacStudio, and it’s not easy to understand who to blame. Anyway, the definitive solution is to use a USB-C to DisplayPort cable. No more problems. The downside is that to use the screens as a USB hub, I had to connect them using the USB-A cable, which is fine because the MacStudio comes with two USB-A ports.
Enough talking about the hardware.
2022-04-15 - One week into using macOS and an M1 for .NET Development.
Let’s start with the easy stuff. JetBrains Rider is a joy. .NET 6, runtime and SDK, are supported on ARM64. We can build and execute all .NET projects targeting .NET, including .NET Core. Obviously, except for WPF and Windows Forms projects. They require Windows anyway.
We can install .NET Core 3.1. There is support only for the x64 version. Not a big deal since it goes out of support soon.
Last but not least, VS Code works great. Its support for dockerized environments comes in handy.
Windows virtualization using Parallels
For everything else, .NET Framework-related, we need a virtual machine or some way to use Windows. Forget about Bootcamp. It doesn’t exist, and it probably won’t ever exist for ARM.
I installed the trial version of Parallels. One caveat for using virtual machines on ARM hosts is that the virtualized operating system needs to be for ARM64. That might open to issues in virtualizing Windows because there is an agreement between Microsoft and Qualcomm that might affect our ability to license Windows for ARM on non-Qualcomm hardware.
That being said, Parallels does an excellent job. Once installed, the virtual machine creation wizard asks a few questions. The first one is what operating system we need, and when I selected Windows 11, it automatically downloaded the required ISO and started the installation. It took a minute, or a little more, to install Windows 11 for ARM.
Windows 11 for ARM, executed in Parallels, is incredibly fast. When used on full screen, it’s hard to perceive that it’s a virtual machine.
Before getting to development, a couple of words about regular, non-development-related applications. I read here and there people complaining about poor performance. For the sake of the experiment, I installed Adobe Photoshop Elements using the 2012 bits, that’s the license I own, and Audacity. Both are x64 applications that, at runtime, will go through the x64 to ARM emulation. No issues so far; they work. And they are as fast as they were on my Intel Xeon workstation.
Development tools on Windows for ARM
Visual Studio 2022 is not supported. The installation works fine, and like for other applications, Visual Studio runs smoothly. It’s a bit slower than on my previous workstation, not that it was stellar fast before. All in all, JetBrains Rider was still providing a better experience (except for the application’s first startup time).
The only way to install .NET Framework developer packs was to manually download the needed installers instead of the Visual Studio Installer. The Visual Studio Installer installs them, but then Visual Studio complains they are unavailable.
I tried compiling a couple of solutions, intentionally selecting challenging ones. It worked. Tests were green too.
All .NET 6 projects, as expected, compile and run fine.
One last note: .NET 3.1 is tricky. As said, it comes only with x64 support. Visual Studio asks to install it:
I downloaded the SDK installer based on my previous experience with the developers’ pack. It fails. The error is that ARM is not a supported platform, which is an interesting error because we can install the same x64 SDK on the M1 Mac. The .NET Core 3.1 SDK installs fine using the Visual Studio Installer. But then I started getting all sorts of weird errors from Visual Studio. I suppose a lot of the Visual Studio tooling depends on .NET Core that tries to load other assemblies compiled for ARM, causing many operations to fail. Removing .NET Core 3.1 solved my problems. I assume that Visual Studio uses the latest runtime, .NET 6, in my case, if the expected one is not available. I have no idea how many latent problems are waiting for me around the corner.
2022-06-27 - A couple of months into using macOS and an M1 for .NET Development.
The following section is only about .NET development, specifically WPF, using the Parallels Windows for ARM virtual machine. I have no issues with .NET 6 or .NET 7 development using macOS. Everything I need works as expected.
When using the Windows for ARM virtual machine, Visual Studio 2022 is extremely slow when developing WPF code, regardless of editing XAML files or regular C# ones. JetBrains Rider helps a lot. It’s much more performant and an excellent Visual Studio replacement for most workloads.
There is no way, or at least no way I know to debug WPF applications using Visual Studio 2022. The application starts, the debugger is attached, and the WPF LivePreview tools work as expected. However, no breakpoint is hit. All of them show as disabled with the “no symbols loaded” error. Again, debugging works flawlessly in JetBrains Rider.
Microsoft recently released the Visual Studio 2022 Preview 2 for ARM. It’s a game-changer. It’s fast, faster than JetBrains Rider, and despite being the first preview, it’s pretty stable. I have had no issues so far. Breakpoints don’t work, though. I have a feeling that the culprit is the target framework. The application I’m working on targets .NET 4.8, which doesn’t come with ARM support. There will be a .NET 4.8.1 targeting the ARM platform, which probably also addresses the debugging issue I’m facing.
2022-09-19 I’m ready to give up — .NET Framework development is a PITA
A remark: I probably spent 30% of my time writing code in my current role. In the vast majority of the cases, the development stack is C# and .NET 6. It doesn’t need Windows and works flawlessly on macOS using the excellent JetBrains Rider.
If the project multi-targets .NET and .NET Framework, and you know what to do (e.g., there is no need for full IntelliSense support to detect that a member is unavailable in one of the targeted frameworks), then macOS is again more than enough. The production build artifacts are a CI concern.
I recently upgraded Visual Studio 2022 for ARM to the latest preview bits, and none of the test-related things work. That effectively breaks .NET Framework development using the Windows for ARM virtual machine. I created an Azure virtual machine and use that for the few .NET Framework development needs I still have.
I will check if newer Visual Studio bits improve the situation from time to time, but that’s a dead end for now.
To be continued.
Photo by Mark König on Unsplash