Improving C# Memory Safety(devblogs.microsoft.com)
111 points bysoheilpro2 days ago |6 comments
gertlabs1 hour ago
C# is one of the best languages we evaluated for LLM problem solving. In fact, many strongly typed, lower level languages perform well in our testing (this isn't to say that the solutions are more maintainable, but the LLMs come up with better ideas when writing C# or Rust than Python). Google models especially, for whatever reason, outperform in C#, not Golang.

Data at https://gertlabs.com/rankings?provider=google

superjan6 hours ago
What you can do in C# today is convert any unsafe pointer to Span whenever you get your hands on it, and pass around slices. You can still drop down to ‘fixed’ when it turns out you need it for performance.
pjmlp1 day ago
Most likely a side effect related to Windows team finally giving some C# love, instead of COM and C++, given the comparisons between C# 16 with Rust and Swift in a few article sections.
moomin5 hours ago
The Windows team is talking to DevDiv again? Satan's putting on his ice skates right now.
pjmlp4 hours ago
One can only hope.

C++/WinRT is in maintenance, and you will notice the WinUI 3.0 does most of their demos, and gallery with C#.

moomin2 hours ago
It would be nice if any display API actually covered the entire API with the exception of the actual OS API…
Dwedit1 hour ago
Are they finally marking all those functions that use IntPtrs as unsafe? (such as Marshal.Copy)
orphea58 minutes ago
Not really, because IntPtr is just a native-sized integer.

Marshal.Copy will certainly be marked unsafe, as will anything else that touches unmanaged memory.

caspper692 hours ago
They are aligning more closely with the Rust 2024 model for unsafety, which requires inner annotations at the point of unsafety in addition to notation of the function (unless it is the safe-unsafe boundary) plus it imposes a requirement for a SAFETY doc notation for describing the specific invariants the caller must enforce to uphold the safety guarantees. Not terribly onerous in my opinion. I maintain a few native library wrappers on nuget, so I will have to do some updates around IntPtr usage, but this doesn’t seem like it will be terribly painful in my case. Thankfully I don’t do much marshalling. Plus you get a nifty badge on nuget for making your library safe.

The blurb toward the end about Rent/return makes me a bit nervous though. They say they’re not going full borrow checker, but rent at least sounds an awful lot like borrow to me. Details were basically non-existent though.

I guess I wonder what the end game is here though. The more they make C# like Rust with a GC, the less incentive people have to use C# except maybe to support legacy work. I am still far more comfortable in C# than Rust, and I believe C# is superior for e.g. web, but over time this advantage could be lessened quite a bit as the Rust ecosystem continues to grow.

masklinn47 minutes ago
> The blurb toward the end about Rent/return makes me a bit nervous though. They say they’re not going full borrow checker, but rent at least sounds an awful lot like borrow to me. Details were basically non-existent though.

Since they state outright that they're not going for a borrow checker, I would assume they're going for "second class references": the borrow checker is both powerful and complicated because references are first-class types: you can pass a reference as parameter, you can return a reference, and you can store a reference.

You can get a lot of the benefits (though also lose a fair amount of expressive power) if you drop the last two and only allow borrows downwards, and that is way easier to track.

Graydon Hoare's original conception of rust used second-class references (https://graydon2.dreamwidth.org/307291.html#:~:text=First-cl...). The Val language uses second-class references. Hylo (formerly Val) uses second-class references under the name of mutable value semantics (https://www.jot.fm/issues/issue_2022_02/article2.pdf).

Although the rent/return case doesn't even seem like a references concern, instead it's affine types which is orthogonal: after you `Return` an array to the pool, you want the array to become inaccessible to the caller (you could make the value linear, but as the text explains missing a `Return` is a safe leak it doesn't look like that's in scope). Rust mutable references are affine but you don't need references to do this...

SideburnsOfDoom4 hours ago
> The unsafe keyword is being redesigned

OK, I see a lot of C# code often and over a long time.

I see the "unsafe" keyword used approximately never.

I'm sure that this is useful for some cases. But not everyday things for most of us. If we did use it, it would be carefully isolated in a library for a specific purpose.

tialaramex3 hours ago
This moves C# to a more modern systematic understanding of what this keyword is for, but it'll remain very rare in C# the same way it's rare in Rust, and presumably in Swift.

The choice of keyword "unsafe" is partly psychological. Turns out if you called this exact same feature "trusted" or whatever the programmers don't have the appropriate feelings about it. They want to write trusted code, they don't want to write unsafe code, so making them write the keyword "unsafe" provides that psychological disincentive.

pixl972 hours ago
Initialize liveHandgrenade;
zmj2 hours ago
There are standard library APIs that let you do memory-unsafe things without the unsafe keyword (CollectionsMarshal, MemoryMarshal). They're useful, but the burden is on the caller to uphold the invariants. This proposal seems aimed at making that kind of contract more explicit and obvious.
pjmlp3 hours ago
Many of us use it in scenarios where others would write a blog post about a rewrite in Rust, C++ or whatever.

CLR was designed to support languages like C++, yet many don't learn the knobs.

Weebs1 hour ago
Any lesser known knobs one should know? I'm considering a .NET backend for my compiler
pjmlp1 hour ago
If on Windows, one is to see what C++/CLI would generate, with ildisam or similar tool.

You can also emit MSIL for what you actually want to do, with low-level bytecodes.

Then there is unsafe, ref structs, stack allocation, fixed buffers, scoped types, manual memory management, array pools, memory pipelines, the various span variants.

Profan2 hours ago
In a game development context, especially where C++ interop is involved and a lot of code lives across a boundary where memory is owned by C++ but you want to avoid/minimize marshaling overhead or just generally maximize performance, the unsafe keyword is quite handy, but outside of those you can indeed probably get around by approximately never using it.

There's a lot of power C# gives you if carefully curated, making a lot of cases where people previously might have seen C++ as the only option as suddenly quite viable.

... See also the somewhat arcane Unsafe.As etc APIs

Quothling3 hours ago
Around here C# is only really used at stagnant middle sized companies with horrible code bases. The sort where the company follow Uncle Bob religiously, while completely misunderstanding everything Uncle Bob ever said. Doesn't mean the language (and it's runtime) can't be good.
caspper692 hours ago
Yes, many people instinctively stay away from anything microsoft (except github, typescript and npm). But the stack is solid. I’m always reminded of Stack Overflow and how they built on asp.net and like 7 servers and it scaled very well for years.

Everyone has what they like and what they’re familiar with, and for better or worse, especially for startups it’s rarely .net. But I couldn’t imagine e.g. using js instead on the back end, but that’s just me.

Weebs1 hour ago
A VM with good FFI and structs is pretty unique and all of the tooling around .NET is excellent

F# is a sleeping giant of capability in the FP/ML space, being able to use a lot of the existing tooling

People rightfully point out how it's sort of second class in comparison to C# at times, but its still A tier tooling that few languages have

smt883 hours ago
C# is like Rust in the sense that a regular (web, desktop, etc.) developer probably won’t need unsafe, but it’s useful for lower-level work in libraries and CLI tools, especially where performance is important.