Edit: Added a case where an HSM isn't necessarily the solution
As you mentioned, a decompiler can get at your keys; that's part of the reason that you should NEVER have a decryption key hard-coded (a hard-coded public key to encrypt for is less bad).
If I mis-understood the question and your key isn't hard-coded but you're trying to hide the key when it isn't needed then an API like ProtectedData.Protect may what you are looking for.
But depending on what you're doing, that may not be the right answer (who is your attacker? what are you defending from?).
Defending from:
- A Watson dump that gets sent to Microsoft containing the key
- ProtectedData.Protect (or HSM)
- An arbitrary-memory-read security vulnerability in your code being exploited by a remote attacker
- ProtectedData.Protect (or the sarcastic "don't write that kind of vulnerability", or HSM)
- An administrator (legit or otherwise) being able to attach a debugger and read the key
- Move the key to a Hardware Security Module (HSM)
- Your process being paged out and an administrator being able to read it from the pagefile
- An arbitrary-execute security vulnerability in your code being exploited by a remote attacker
- Your system hibernating and the hibernation payload being read by someone who steals your hard drive
- A process crash dump that is still on the hard drive and the drive gets stolen
- The entire computer gets physically stolen
- BitLocker (but not necessarily an HSM, since that would have been stolen, too).
You'll note that the list of things that you can actually defend against with memory protection is small. Much better is making it so that nothing can ever read the key, by moving it to an HSM. Windows CNG supports symmetric encryption via an HSM, and .NET 4.6.2 (currently in preview) supports utilizing this behavior with the AesCng(string, CngProvider) constructor.