Pointer Arguments

Somewhat of a niche guideline... but I got questions
internally so it seemed worth writting it down and sharing with
you.

 

As always, comments welcome

--------------------------------------------------

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.

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

[CLSCompliant(false)]

public unsafe int GetBytes(char* chars, int charCount,

byte* bytes, int byteCount);

public int GetBytes(char[] chars, int charIndex, int
charCount,

byte[] bytes, int byteIndex, int
byteCount)

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. 

 

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.

//Bad practice

public unsafe int GetBytes(char* chars, int charIndex, int
charCount,

byte* bytes, int byteIndex, int
byteCount)

 

//Better practice

public unsafe int GetBytes(char* chars, int charCount,

byte* bytes, int
byteCount)

 

//example callsite

GetBytes(chars + charIndex, charCount, bytes + byteIndex,
byteCount);

Annotation
(Brad Abrams): For developers working with pointer based APIs it is more natural
to think of the world in a pointer-oriented mindset. 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.