你应该在C#中使用指针(不安全的代码)?

你应该在你的C#代码中使用指针吗? 有什么好处? 是否由The Man(微软)推荐?

从“男人”本人:

在C#中很less需要使用指针,但有些情况需要它们。 作为示例,使用不安全的上下文来允许指针是由以下情况下的保证:

  • 处理磁盘上的现有结构
  • 高级COM或平台调用scheme,涉及结构与指针在其中
  • 性能关键的代码

不鼓励在其他情况下使用不安全的上下文。

具体来说,不应该使用不安全的上下文来尝试在C#中编写C代码。

警告:

使用不安全上下文编写的代码不能被validation是安全的,所以只有在代码完全可信时才会执行。 换句话说,不安全的代码不能在不受信任的环境中执行。 例如,您不能直接从Internet运行不安全的代码。

参考

如果你必须。

假设你需要伪造一个大的灰度图像,比如2000×2000像素。 首先使用GetPixel()SetPixel()编写“安全”版本。 如果这样做,伟大的,继续前进。 如果certificate速度太慢,则可能需要查看构成图像的实际位(为了示例,不要考虑颜色matrix)。 使用不安全的代码没有任何坏处,但是增加了项目的复杂性,因此只能在必要时使用。

我不记得曾经这么做过 – 但我没有做太多的交stream。 这是最常见的应用程序,我相信:调用本机代码。 有几次使用指针可以让你优化一些代码,但是在我的经验中这是非常罕见的。

如果是任何指南,我认为自己在C#中非常有经验,但如果我不得不做任何不安全的代码,我不得不咨询spec / books / MSDN来指导我。 当然,会有很多人对不安全的代码感到满意,但对查询expression式不太熟悉。

我想说的主要问题是:

  • 不安全的代码是不可validation的。 这意味着代码只能由完全可信的上下文中的用户运行,因此,如果您需要用户从任何不是完全可信的地方运行代码(例如未configurationnetworking共享),那么您拧紧。
  • 缺乏可validation性(不知道这是否真的是一个字)也意味着你可能弄乱你的程序中的内存。 您可能会将整个类别的错误带回您的应用程序 – 缓冲区溢出,悬挂指针,yada yada yuck yuck。 更不用说可能会破坏内存中的数据结构,而不会意识到指针何时变得怪异。
  • 如果你想让你的不安全的代码访问pipe理对象,你需要“钉住”他们。 这意味着GC不允许在内存中移动对象,因此托pipe堆可能变成碎片。 这有性能影响; 因此,确定是否有任何潜在的性能增益没有超过这个问题是非常重要的。
  • 对于不习惯于非托pipe方法的程序员,您的代码变得难以理解。 然后,他们可能更容易用一些“自由”不安全的代码给他们一些脚步。
  • 您可以编写非types安全的代码; 这真的相当消除了一个很好的温暖的模糊托pipe语言的优势。 现在你可能会遇到可怕的types安全问题。 为什么要倒退呢?
  • 它使你的代码丑陋

我相信还有更多可以添加到列表中。 一般来说,正如其他人所说 – 避免,除非你必须通过p / invoke调用一个非托pipe方法,这需要一些特殊的指针funking。 即使这样,编组人员大多会阻止对此的需求。

基本上,“男人”也要说避免。

哦,好的文章关于固定MSDN的方式。

不安全的代码是.NET CLR完全支持的function。 好处是性能和与二进制代码的兼容性。 运行时是一个防止你崩溃和燃烧的沙箱,但这是一个成本。 在对存储器中的大块(例如image processing)进行极其严格的操作的情况下,超出运行时提供的正常安全性的速度会更快。

说了这么多,我觉得这里大多数人会说“不要这样做”。 绝大多数.NET开发人员在正常的活动中不会遇到这种情况,只能通过使用不安全的代码来解决。

我使用不安全的代码来使用模拟来允许服务访问networking共享。 如果你知道你在做什么,这不是一个问题。

如果你需要的话,你应该使用它们; 大多数情况下,这将是处理一些棘手的互操作场景(例如,当我在.NET 1.0中编写DPAPI的托pipe包装时,需要它们),但偶尔可能会通过使用stackalloc或类似的方式来提高性能(分析后!

微软推荐他们和C#的devise者一样多,他们决定增加编写unsafe代码的能力。 您可以从关键字的select以及要使用关键字描述您所写的方法/类的要求中看到,它不是实际select的实际select。

类似于不由BitConverter提供的转换的解释。
特别是将一个unint转换成一个用于散列函数的int,你所关心的只是位。

在结构上使用一些有用的,很好理解的关于c或c ++惯用函数的地方,你需要将它们作为一个众所周知的长度的字节*再次用于散列。

在内存结构中(非常具体的)极其快速的二进制序列化(通过对它们进行数组操作),尽pipe老实说,只需要删除到C ++ / CLI即可。

必须说,在许多情况下,需要指针的任务通常可以通过在C ++ / CLI中执行,然后将其作为一个dll导入到C#项目中来解决。 它不会改变代码是否是“安全的”,但是它使得一些有用的函数可以在基于指针的结构上更容易操作。 如果你真的想要的话,它也可以让你混淆generics或枚举。

大多数开发者需要这样做的可能性确实很遥远。 有用的时候,虽然你需要它…

当然这不是“推荐”,这就是为什么它被标记为“不安全”。 但是别让这个吓跑你 虽然,它应该让你看看你的代码两次。 也许有一个pipe理的方式来做到这一点?

使用不安全的代码就像忘记了.Net框架的好处,我曾经使用它们来创build像堆栈和东西的老式结构,但这只是为了学校,现在我还没有需要使用它们。

如果它使您的代码更短,更清晰,那就做吧。

“按照你的意愿,适当考虑到拐angular处的警察。” WSM