Add GetLParam<T> and GetLParamRef<T>#835
Conversation
|
cc @JeremyKuhne |
|
honestly LGTM; I don't really understand the implications however... |
|
@jkotas, @stephentoub, @jkoritzinsky Any feedback on using this |
|
I think it is better to stick to regular unmanaged pointers for interop. It makes the intent much more obvious. For example, I do think that the following change is an improvement? NativeMethods.WINDOWPOS* wp = (NativeMethods.WINDOWPOS *)m.LParam;to ref NativeMethods.WINDOWPOS wp = ref m.GetLParamRef<NativeMethods.WINDOWPOS>(); |
|
@danmosemsft I'll take a look Monday |
I investigated this change this morning, and my conclusion is I do not believe the change leads to an improved outcome. There is no pointer representation equivalent to Managed references also does a better job of restricting the locations where unsafe operations are used. |
Codecov Report
@@ Coverage Diff @@
## master #835 +/- ##
===================================================
+ Coverage 28.83584% 28.83972% +0.00388%
===================================================
Files 1078 1078
Lines 293919 293921 +2
Branches 38408 38408
===================================================
+ Hits 84754 84766 +12
+ Misses 205131 205118 -13
- Partials 4034 4037 +3
|
It is matter of personal preference. Here is a quick summary of pros and cons: Managed references:
Unmanaged pointers:
I prefer leaner and faster code with explicit unsafe because of it is much easier to see that is going on. I believe it is also where the CoreCLR/CoreFX repos are leaning towards. If other folks prefer the opposite and understand consequences of such preference, I do not have a problem with it. Ultimately, it is up to the WinForms maintainers to make the choice. |
|
I believe the perceived magnitude of this downside differs between us:
The pointers don't represent the way I would write (or suggest others write) C#. It doesn't mean it can't be done that way (it's a matter of style, not correctness), but if managed references aren't a possibility here it would likely save a bunch of time to go ahead and close this.
I would expect this to improve over time as managed references become the preferred style for users. |
I agree with this when it comes to direct interop with native code, particularly at these low levels of the stack. I believe there is value in giving uplevel code the best performance possible. On top of performance, the obfuscated "unsafeness" concerns me when it comes to long term maintenance. You can mitigate that somewhat by liberally putting
Quite possibly, but we should be very cautious about taking hits based on potential future improvements.
For the record, that isn't me. I'm on the CoreFx team, and I'm here because I've been spending quite a bit of time on interop and I also am very interested in seeing interop improved in WinForms and WPF. |
I wouldn't be opposed to this. We can't use |
Well, not without adding |
I don't think this will ever get as slim as raw pointers. You also have other issues, such as not being able to accurately handle/represent things like |
| if(nmhdr->code == NativeMethods.TTN_SHOW) { | ||
| m.Result = UnsafeNativeMethods.SendMessage(new HandleRef(null, nmhdr->hwndFrom), Interop.WindowMessages.WM_REFLECT + m.Msg, m.WParam, m.LParam); | ||
| private void WmNotify(ref Message m) { | ||
| ref readonly NativeMethods.NMHDR nmhdr = ref m.GetLParamRef<NativeMethods.NMHDR>(); |
There was a problem hiding this comment.
Is there actually any guarantee that the underlying nmhdr is readonly or are you just using this to say the local WmNotify shouldn't modify the state?
| { | ||
| IntPtr srcPtr, destPtr; | ||
| if (IntPtr.Size == 4) { | ||
| srcPtr = new IntPtr(sourceData.Scan0.ToInt32() + offsetSrc); |
There was a problem hiding this comment.
IntPtr has a operator +(IntPtr pointer, int offset) method.
|
hey @sharwell , i kind of fell out of touch here while i was OOF; how is this going? |
|
@jkotas , @tannergooding , and @JeremyKuhne -- could one of you please approve when your perspective is satisfied? @sharwell pinging again 😄 |
|
@zsd4yr, I think the perspective given so far was that this PR is largely unnecessary and sticking with raw pointers/unsafe code is probably better (e.g: #835 (comment)). |
This pull request implements the new
GetLParam<T>andGetLParamRef<T>(#792) as internal methods, and uses them to avoid marshaling overhead for existing value types.The first commit is shared with #818.