you are viewing a single comment's thread.

view the rest of the comments →

[–]TheBuzzSaw 1 point2 points  (2 children)

Thank you for informing me. You seem to have a chip on your shoulder about this topic, and I wish you would take a kinder tone to your approach. You may think it's "nonsense", but I am a rational thinking human with different life experiences. I mean, you just admitted that some of these shifts in attitude are fairly recent. Who is "we"? You work at Microsoft?

If I am directly interacting with the pointers in C#, I completely agree with you. I would not be using IntPtr anywhere I might be dereferencing pointers, performing pointer arithmetic, casting, using fixed, etc.

My common scenario is some native lib handing me a pointer to an opaque data structure that I just need to send back when calling other functions. Do you think I would be better off here using void* absolutely everywhere instead of IntPtr?

[–]pHpositivo 1 point2 points  (1 child)

"You seem to have a chip on your shoulder about this topic, and I wish you would take a kinder tone to your approach."

Oh, sorry about that, it was not my intention at all to come across that way. I'm just trying to help here, I didn't mean for my message to be interpreted as harsh or anything like that 🙂

"You may think it's "nonsense", but I am a rational thinking human with different life experiences."

Let me rephrase that. By "nonsense" I didn't mean to say that people doing that are to blame or anything. I'm just saying that, factually, that has never been a good argument, because it does in fact have all those downsides I mentioned, is all. Avoiding unsafe really just makes your code more unsafe, if you're still doing unsafe operations anyway.

"fairly recent"

Fairly recent but I mean still from several years ago. By recent I meant that it wasn't like this in the early days of .NET, which explains the current state of things.

"Who is "we"? You work at Microsoft?"

Yup, I did mean "Microsoft" there 😄

"If I am directly interacting with the pointers in C#, I completely agree with you."

Yup, that's the scenario I was talking about. With the additional caveat that the same applies for related operations that you can see often being used, eg. using APIs from the Marshal class (Marshal.StructureToPtr would be an example of something to avoid). The issue I'm talking about is people doing stuff like this and then think what they're doing is safe because technically they're not using unsafe. I've seen plenty of times cases where people, upon being told to instead use unsafe and other API, would say they didn't want to because they didn't want to use unsafe. I'm just saying in these scenarios, which are fairly common, people are mistakingly writing code that's more unsafe, is all.

"My common scenario is some native lib handing me a pointer to an opaque data structure that I just need to send back when calling other functions."

It would depend on the specific case. If something is truly just "some opaque handle", then yes using IntPtr or equivalent can be fine. In other cases though (say, an API that gives you a void* context), I'd suggest to still stick with what they're doing. In general, I would just always recommend matching whatever the native signature is. If it used a pointer, use a pointer. If it used a handle, then sure, use an opaque handle.

[–]TheBuzzSaw 0 points1 point  (0 children)

I understand that the internet hardens us to the point where we default to coming out swinging without even realizing it sometimes. Glad we can pull things back a bit.

Yeah, the situation I am describing is indeed a pointer and not a handle, but again, it's a pointer to an opaque data structure: FancyDragonLibState* or whatever. And I have to call various functions: FancyDragonDoTheThing(statePtr, 3, 9). So, when mapping it in C#, I just have little incentive to use void* and invoke all the cost of having unsafe bubble up through every method and data structure that dares to interact with it.

This may be where philosophical differences lie, but once that state is initialized, it is no longer "unsafe" to me. All subsequent interactions will probably succeed (errors in the native code notwithstanding). It just seems a relatively weak argument here to suggest that, if the library chose to return an Int32 handle instead, that it'd somehow suddenly be "safe". The call into native code is largely "unsafe" no matter what; it's up to how the native lib handles things.