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.