Should you use pointers in your C# code? What are the benefits? Is it recommend by The Man (Microsoft)?
I can't remember ever having to do so - but I haven't done much interop. That's the most common application, I believe: calling into native code. There are a very few times where using pointers allows you to optimise some code, but it's pretty rare in my experience.
If it's any guide, I consider myself to be pretty experienced in C# but if I had to do any unsafe code I'd have to consult the spec/books/MSDN to guide me. Of course there will be plenty of people who are happy with unsafe code but less familiar with (say) query expressions...
You should use them if you need them; mostly this will be when dealing with some tricky interop scenarios (for example when I wrote a managed wrapper for DPAPI in .NET 1.0 they were needed) but very occasionally it might be to improve performance (after profiling!) by using stackalloc
or similar.
It is recommended by Microsoft in as much as they are the designers of C#, and they made the decision to add the capability to write unsafe
code in it. You can see from the choice of keyword and the requirement to delineate the methods/classes in which you write it using the keyword, that it isn't designed to be the de-facto implementation choice.
course it isn't "recommended", that's why it's labeled "unsafe". But don't let that scare you away. Although, it should make you look twice at your code. Perhaps there is a managed way to do it?
Unsafe code is a fully supported function of the .NET CLR. The benefits are performance and compatibility with binary code. The runtime is a sandbox which prevents you from crashing and burning, but that comes with a cost. In situations where you are doing extremely intensive operations against large blobs in memory, for example image manipulation, it is faster to step outside the normal safety the runtime provides.
That having been said, I think most people here would say "don't do it". The vast majority of .NET developers will not run into a case in their normal activities that can only be solved by using unsafe code.
If you have to.
Say that you need to false color a large grayscale image, say 2000x2000 pixels. First write the 'safe' version using GePixel() and SetPixel. If that works, great, move on. if that proves to be too slow, you may need to get at the actual bits that make up the image (forget about Color matrices for the sake of the example). There is nothing 'bad' about using unsafe code, but it adds complexity to the project and should thus be used only when necessary.
I used unsafe code to use impersonation to allow services access to network shares. It is not a problem if you know what you're doing.
From "The Man" himself:
The use of pointers is rarely required in C#, but there are some situations that require them. As examples, using an unsafe context to allow pointers is warranted by the following cases:
- Dealing with existing structures on disk
- Advanced COM or Platform Invoke scenarios that involve structures with pointers in them
- Performance-critical code
The use of unsafe context in other situations is discouraged.
Specifically, an unsafe context should not be used to attempt to write C code in C#.
Caution:
Code written using an unsafe context cannot be verified to be safe, so it will be executed only when the code is fully trusted. In other words, unsafe code cannot be executed in an untrusted environment. For example, you cannot run unsafe code directly from the Internet.
using Unsafe code is like forgetting the benenfits of the .Net Framework, i used them once to created old fashioned structures like stacks and stuff but that was only for school, nowadays i havent had the need to use them.
Do it if it makes your code shorter and clearer.
"Follow your inclinations with due regard to the policeman round the corner." WSM
Reinterpretive like casts not supplied by BitConverter.
Specifically converting a unint into an int for hash functions where all you care about is the bits.
Using some useful, well reasoned about c or C++ idiomatic functions on structs where you need to treat them as a byte* of a well known length, again most useful for hashing.
Extremely fast binary serialization of (very specific) in memory structs (by doing it to an array of them) though to be honest this is better done by just dropping to C++/CLI.
It must be said that in many cases the task requiring pointers can often be solved better by doing it in C++/CLI and then importing this into you c# project as a dll. It doesn't change whether the code is 'safe' or not but it makes a bunch of useful functions for operating on pointer based structures more accessible. It also allows you to mess about with generic types or enums if you really want to.
The likelihood of most developers needing to do this is indeed remote. Useful when you need it though...
I would say the main issues are:-
- Unsafe code is not verifiable. This means that the code can only be ran by a user from an entirely trusted context, thus if you ever need a user to run the code from anywhere less than entirely trusted (e.g. a network share not configured to be so), you're screwed.
- Lack of verifiability (hm not sure if that's actually a word) also means you could potentially mess up memory in your program. You are potentially bringing whole classes of bugs back into your application - buffer overruns, dangling pointers, yada yada yuck yuck. not to mention being potentially able to corrupt data structures in memory without realising when your pointer goes weird.
- If you want your unsafe code to access managed objects you need to 'pin' them. This means the GC is not allowed to move your object around in memory and thus the managed heap can become fragmented. This has performance implications; therefore it's always important to determine whether any potential perf gain isn't outweighed by this issue.
- Your code becomes harder to understand for programmers not used to the unmanaged approach. They may then be more liable to shoot their foot off with some of the 'freedom' unsafe code gives them.
- You become able to write un-type-safe code; this really rather eliminates a lot of the advantage of a nice warm fuzzy managed language. Now you can encounter horrible type safety issues. Why take that step backwards?
- It makes your code uglier.
I'm sure there's more that could be added to the list; in general, as others' have said - avoid unless you have to.e.g. calling an unmanaged method via p/invoke which requires some special pointer funking. Even then the marshaller will mostly prevent the need for it, mostly.
'The man' also say avoid unless necessary, basically.
Oh, nice article about pinning here on MSDN by the way.