11

Read this question today about safe and unsafe code I then read about it in MSDN but I still don't understand it. Why would you want to use pointers in C#? Is this purely for speed?

Community
  • 1
  • 1
Lumpy
  • 3,632
  • 4
  • 34
  • 58
  • 15
    If you are a sensible person then you don't ever *want* to use pointers in C#. They are there for those situations where you *have* to use pointers in C# whether you *want* to or not. :-) – Eric Lippert May 03 '10 at 21:56

4 Answers4

25

There are three reasons to use unsafe code:

  • APIs (as noted by John)
  • Getting actual memory address of data (e.g. access memory-mapped hardware)
  • Most efficient way to access and modify data (time-critical performance requirements)
Keith Adler
  • 20,880
  • 28
  • 119
  • 189
  • 6
    For time-critical application using .net is not smart anyway. The GC is non-deterministic and can kick in every moment. Which basically screws up you time-critical app. Other points i agree btw! – Henri May 03 '10 at 20:31
  • 2
    Another reason I've heard cited for using unsafe C# is to be sure that security-sensitive information, such as a password or private encryption key, is removed from memory at a deterministic point in time. Otherwise, a password can hang around in memory until someone else wants to write to the same locations. – harms May 03 '10 at 21:09
5

Sometimes you'll need pointers to interface your C# to the underlying operating system or other native code. You're strongly discouraged from doing so, as it is "unsafe" (natch).

There will be some very rare occasions where your performance is so CPU-bound that you need that minuscule extra bit of performance. My recommendation would be to write those CPU-intesive pieces in a separate module in assembler or C/C++, export an API, and have your .NET code call that API. An possible additional benefit is that you can put platform-specific code in the unmanaged module, and leave the .NET platform agnostic.

John Källén
  • 7,551
  • 31
  • 64
  • 1
    Why do you recommend switching languages for performance-sensitive code? The advantages are not at all clear. Why not use the full features of the C# language? – Jeffrey L Whitledge May 03 '10 at 20:29
  • Right tool for the right job? If I'm going to monkey around with pointers and other low-level work, I'd rather do it with C/C++, where I have a lot of tools at my disposal. Useful things like inline assembler, based pointers and other bit-pushing stuff is not supported in C#. – John Källén May 03 '10 at 20:32
  • I agree, when writing in assembler or C you need to be concerned with how you code was compiled. – ChaosPandion May 03 '10 at 20:32
  • The performance you gain with using assembler or optimized code is largely gone when doing marshalling from C# to C and back. – Henri May 03 '10 at 20:35
  • 3
    Even with unsafe C#, you're still working in the managed environment. The JIT can target the right CPU, and perform other optimizations (like inlining methods) when it's appropriate to do so. If you don't need to extra features of another language, and you're already writing in C#, and you want to do pointer manipulations to improve performance, then I think "unsafe" C# is the right way to go. – Jeffrey L Whitledge May 03 '10 at 20:41
  • 1
    I can agree with you that if all you are doing is waltzing on a memory chunk and not calling platform specific functionality, that it's probably reasonable to stay within the confines of C#. @Henri: You'd try to ensure that your unmanaged API is granular enough that you don't need to call it in a tight loop where marshalling is going to eat up your performance. Just like you don't draw a bitmap by calling SetPixel() width * height times, but call BitBlt instead. – John Källén May 03 '10 at 20:48
4

I tend to avoid it, but there are some times when it is very helpful:

  • for performance working with raw buffers (graphics, etc)
  • needed for some unmanaged APIs (also pretty rare for me)
  • for cheating with data

For example of the last, I maintain some serialization code. Writing a float to a stream without having to use BitConverter.GetBytes (which creates an array each time) is painful - but I can cheat:

float f = ...;
int i = *(int*)&f;

Now I can use shift (>>) etc to write i much more easily than writing f would be (the bytes will be identical to if I had called BitConverter.GetBytes, plus I now control the endianness by how I choose to use shift).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 3
    I understand why you do it, but that code in C# just makes me cringe. – Stephan May 03 '10 at 20:33
  • I just had to laugh when I saw this one: `for cheating with data`. You crack me up my friend! I can't say I've ever done it, but the example makes perfect sense! – Mike Perrenoud Nov 12 '13 at 14:34
0

There is at least one managed .Net API that often makes using pointers unavoidable. See SecureString and Marshal.SecureStringToGlobalAllocUnicode.

The only way to get the plain text value of a SecureString is to use one of the Marshal methods to copy it to unmanaged memory.

Olly
  • 5,966
  • 31
  • 60