Pointer Arguments


style="MARGIN: 3pt 0in; TEXT-INDENT: 0in; mso-list: none; tab-stops: .5in"> size=2>Somewhat of a niche guideline… but I got questions
internally so it seemed worth writting it down and sharing with
you.


style="MARGIN: 3pt 0in; TEXT-INDENT: 0in; mso-list: none; tab-stops: .5in"> face=Verdana size=2> 


style="MARGIN: 3pt 0in; TEXT-INDENT: 0in; mso-list: none; tab-stops: .5in"> face=Verdana size=2>As always, comments welcome


style="MARGIN: 3pt 0in; TEXT-INDENT: 0in; mso-list: none; tab-stops: .5in">————————————————–


style="MARGIN: 3pt 0in; TEXT-INDENT: 0in; mso-list: none; tab-stops: .5in"> size=2>It is very rare but possible to use pointer arguments
in a well designed framework.  Most
of the time pointers should be encapsulated in a managed instance and thereby
completely hidden.  However in some
cases where interop is a key scenario using pointers is appropriate.


color=#ff00ff size=2> 


face=Verdana>Do provide an alternative for any member that
takes a pointer argument as pointers are not in allowed in the
CLS.


style="MARGIN: 6pt 0in 0pt 0.5in; mso-add-space: auto"> face="Courier New">[CLSCompliant(false)]


style="MARGIN: 0in 0in 0pt 0.5in; mso-add-space: auto"> face="Courier New">public unsafe int GetBytes(char* chars, int charCount,


style="MARGIN: 0in 0in 0pt 2.25in; TEXT-INDENT: 0.25in; mso-add-space: auto"> size=2>byte* bytes, int byteCount); style="mso-special-character: line-break"> style="mso-special-character: line-break">


style="MARGIN: 0in 0in 0pt 0.5in; mso-add-space: auto"> face="Courier New">public int GetBytes(char[] chars, int charIndex, int
charCount,


style="MARGIN: 0in 0in 6pt 2.25in; TEXT-INDENT: 0.25in; mso-add-space: auto"> size=2>byte[] bytes, int byteIndex, int
byteCount)


size=2>Avoid doing expensive argument checking on
methods that take pointer arguments. 
In general argument checking is well worth the cost but for APIs that are
performance critical enough to require using pointers the overhead is often not
worth it. 


face=Verdana> 


face=Verdana>Do use common pointer patterns rather than
managed patterns.  For example there
is no need to pass the start index as simple pointer arithmetic can be used to
accomplish the same result. 


style="MARGIN: 6pt 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New">//Bad practice


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New">public unsafe int GetBytes(char* chars, int charIndex, int
charCount,


style="MARGIN: 0in 0in 0pt 2in; TEXT-INDENT: 0.25in; mso-add-space: auto"> size=2>byte* bytes, int byteIndex, int
byteCount)


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New" size=2> 


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New">//Better practice


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New">public unsafe int GetBytes(char* chars, int charCount,


style="MARGIN: 0in 0in 0pt 2in; TEXT-INDENT: 0.25in; mso-add-space: auto"> size=2>byte* bytes, int
byteCount)


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New" size=2> 


style="MARGIN: 0in 0in 0pt 0.25in; mso-add-space: auto"> face="Courier New">//example callsite


style="MARGIN: 0in 0in 6pt 0.25in; mso-add-space: auto"> face="Courier New">GetBytes(chars + charIndex, charCount, bytes + byteIndex,
byteCount);


style="FONT-SIZE: 10pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-bidi-language: AR-SA; mso-ansi-language: EN-US; mso-fareast-language: EN-US" >Annotation
(Brad Abrams): For developers working with pointer based APIs it is more natural
to think of the world in a pointer-oriented mindset. style="mso-spacerun: yes">  Although it is common in “safe” managed
code, in pointer based code passing an index is uncommon; it is more natural to
use pointer arithmetic.

Comments (2)

  1. theCoach says:

    Manipulating images would be an area that would require pointers, however, the manipulations may be general enough so that many manipulations could be done with managed concepts in tact, and take advantage of leveraging DX and/or the graphics chip. Say I wanted to create an application that allowed a brush to blur the saturation levels that it passes over as defined by the brush and pressure. Is there a recommended way to do that in Windows, and will it change for longhorn with the increased leverage of the GPU? (Can I pass in something like a matrix and a brush definition, and have the system optimize performance better than with pointer manipulation?)

  2. Dmtriy Zaslavskiy says:

    Nice entry. Just one comment (which is somewhat reverse of a bad style you mentioned) there are number of API especially in Graphics that take array as an argument and do not have an overload for passing startIndex and/or size.
    I think this happens when people port C style api where as you mentioned no need to pass startIndex.