C# is garbage collected. Even if the performance potential was as high to begin with (it's not), that's a non-starter for heavy games because you need to be able to control & predict the performance spikes that GC creates. That's even more important for an emulator, which needs more predictability than a regular game.
Emulation involves a lot of large byte arrays and static structs that your code updates a lot to represent the hardware. It isn't necessarily creating a ton of objects all the time. I do not have specifics on hand for these emulators but it's not hard to imagine that they could well be running the GC for a few microseconds every few minutes or something [1]. It is a very different type of program than a traditional game, or, indeed, almost any other kind of program.
There does seem to be this odd semi-subconscious idea in the "GCs aren't appropriate for any high-performance" world that they intrinsically work by stopping the world for 50ms several times per second or something, but that does not have to be the case.
[1]: I actually have a number of servers in Go that run on about this schedule. If you eliminated 100% of my GC cost for these servers, I wouldn't care at all, or even notice.
> Emulation involves a lot of large byte arrays and static structs that your code updates a lot to represent the hardware
Things work a bit differently for "modern" emulators, where the emulators recreate the kernel/OS at a high level. In these emulators, the games will call into the system, and the kernel will be expected to do all thats necessary for the call. In the high level approach, this means that if a call allocates, so does the emulator (edit: note that this is a simplified view, as both emulators map a 4GB page that they work in for the guest system memory, but theres still a ton of side allocations that happen "outside" of the guest kernel). There is a lot of work that goes on in this layer of emulation, and theres going to be objects that the emulator allocates and later destroys. Process tables, thread lists, scheduler information, timing events, kernel synchronization primitives like mutexs, and so on to name some. I'm not intimately familiar with Ryujinx to make any statements about how they handle GC of course, but its something that they'll need to take into consideration. That said, there's plenty of other things like JIT compilation, shader compilation, caches filling up, and on and on that all also cause micro stuttering, so its not uncommon for even C or C++ emulators to have annoying pauses too.
There are a number of ways to control the GC in comfortable ways in C#. https://adamsitnik.com/Array-Pool/ comes to mind, especially for games. So you can lean into GC when possible, and switch to an unmanaged approach when you are seeing perf issues.