microsoft / CsWin32

A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.
MIT License
2k stars 84 forks source link

Add `IsNull` to `nint`/`nuint` based structs for `handle == IntPtr.Zero` checks #1034

Closed elachlan closed 10 months ago

elachlan commented 10 months ago

Is your feature request related to a problem? Please describe. This pattern is used extensively to check if a handle is valid.

Describe the solution you'd like We add this or similar via a partial to multiple classes.

public bool IsNull => Value == nint.Zero;

Describe alternatives you've considered IsValid could be another name for it.

AArnott commented 10 months ago

Looking at HANDLE, I see it already has a static Null property and an instance IsNull property. Now, HANDLE has an IntPtr field, and your subject line suggests you want this for nint typedef structs. But nint isn't necessarily a handle or pointer, so 'null' isn't a concept that directly applies to it. Are there structs that are backed by nint that should rather be treated like handles (thus backing with IntPtr)? Can you name some so I can look into it?

Yes, yes, I know that syntactically IntPtr and nint is nearly identical nowadays. But IMO it's useful to maintain the semantic distinction.

elachlan commented 10 months ago

I think I am repeating myself without realizing I think we looked into it in #610.

Examples:

I think we closed it previously because we wanted to be sure something was a handle vs just a pointer. So anything that was annotated as a handle already has the IsNull property.

jnm2 commented 10 months ago

Yes, yes, I know that syntactically IntPtr and nint is nearly identical nowadays. But IMO it's useful to maintain the semantic distinction.

This came up in the #csharp-lang-design channel in https://aka.ms/dotnet-discord. When some of us were making this point about a semantic distinction, one of the language design team members said:

No, it's literally not a meaningful distinction. It will be normalized for display. It's like int vs Int32.

(https://discord.com/channels/732297728826277939/732297994699014164/1104796983761322105)

AArnott commented 10 months ago

Thanks for sharing, @jnm2. I guess I'll just have to accept that.

Still, if we can tell from the metadata that a one typedef struct represents a pointer and another doesn't, I think it's fair to use that as an indicator to add IsNull in one case and not in another. After all, a handle could legitimately be 0 and still be valid, while a pointer couldn't be 0 and valid. So adding IsNull in both cases could lead to misuse as code assumes IsNull means it isn't valid, but for an opaque handle type, that isn't true.

AArnott commented 10 months ago

Duplicate of #610.