Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional out params should (sometimes?) get an out modifier on friendly overloads #107

Closed
jnm2 opened this issue Feb 17, 2021 · 7 comments
Closed

Comments

@jnm2
Copy link
Contributor

jnm2 commented Feb 17, 2021

Expected: uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowthreadprocessid

@AArnott
Copy link
Member

AArnott commented Feb 17, 2021

The reason no out overload exists is because per the docs, the parameter is optional. C# out forces it to be mandatory. In some APIs, an optional out parameter is important to be able to set at null because doing otherwise can cause the invoked method to do more work (that you may not care about).
In this case of course, it's clear that the whole point of the method is to set this one out parameter, so an out modifier makes sense.

I'm not sure though how to distinguish between the cases where it really should be optional and where it really should be mandatory even though the docs indicate it is optional. I'll leave this issue open to track.

@AArnott AArnott changed the title GetWindowThreadProcessId is missing a friendly out uint overload Optional out params should (sometimes?) get an out modifier on friendly overloads Feb 17, 2021
@jnm2
Copy link
Contributor Author

jnm2 commented Feb 17, 2021

What is the reason not to provide both the friendly overload and the optional pointer overload?

@AArnott
Copy link
Member

AArnott commented Feb 17, 2021

We may do just that. The reason I hesitate is because today the friendly overload (when there is one) applies even when the out parameter should be NULL. If we change it to use an out parameter, folks who don't want to supply the out parameter will be forced to use the extern method itself, which is a little less friendly.
But I suspect the better trade-off is to do as you suggest.

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 17, 2021

In this case of course, it's clear that the whole point of the method is to set this one out parameter

Just clocked this. The return value is the thread ID, so I can envision not caring about the out parameter.

@AArnott
Copy link
Member

AArnott commented Feb 17, 2021

Oh, I hadn't noticed that. Well... interesting then.
I wish C# offered optional out parameters where the called method could tell whether the caller supplied a receiving argument.

@weltkante
Copy link

In this case of course, it's clear that the whole point of the method is to set this one out parameter, so an out modifier makes sense.

If I knew the HWND is my own I'd only be interested in the thread ID and pass NULL for the process id argument in a C++ program. Not sure if its worth the distinction for this particular API (i.e. if it has any observable gain, in C++ it saves you from allocating a stack variable).

Most optional outputs are optional for a reason though, so I'm not sure if there is any point teaching the mappings to override that. If its important to your own coude you probably could easily make an extension method and I'd assume it to be inlined by the JIT in most cases?

@AArnott
Copy link
Member

AArnott commented Feb 25, 2021

At the moment, @weltkante, I'm mostly interested in exploring the broad codegen policies to make most APIs work well. After that, we may consider touch-ups to individual APIs if they are popular and high value enough to do the work in the generator.

I learned more about how to do optional out and ref parameters in C# recently and opened an issue with details a few days ago, having forgotten we already had this issue. But as the other issue has the plan in it, I'm going to close this one in favor of #137.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants