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

时间:2009-02-24 23:35:40

标签: c# .net pointers coding-style unsafe

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

11 个答案:

答案 0 :(得分:36)

来自“男人”本人:

C#中很少使用指针,但有些情况需要它们。例如,在以下情况下使用不安全的上下文来允许指针:

  • 处理磁盘上的现有结构
  • 高级COM或平台调用涉及其中包含指针的结构的方案
  • 性能关键代码

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

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

注意:

使用不安全上下文编写的代码无法验证是否安全,因此仅在代码完全受信任时才会执行。换句话说,不安全的代码不能在不受信任的环境中执行。例如,您无法直接从Internet运行不安全的代码。

Reference

答案 1 :(得分:21)

如果必须的话。

假设您需要对大灰度图像进行伪彩色,比如2000x2000像素。首先使用GetPixel()SetPixel()编写“安全”版本。如果有效,那么继续前进吧。如果证明太慢,你可能需要得到构成图像的实际位(为了示例,忘记颜色矩阵)。使用不安全的代码并没有“坏”,但它增加了项目的复杂性,因此只能在必要时使用。

答案 2 :(得分:12)

我不记得曾经这样做过 - 但我没有做太多的互操作。这是最常见的应用程序,我相信:调用本机代码。很少有几次使用指针允许你优化一些代码,但在我的经验中这是非常罕见的。

如果是任何指南,我认为自己在C#方面经验丰富,但如果我不得不做任何不安全的代码,我必须查阅spec / books / MSDN来指导我。当然会有很多人对不安全的代码感到满意,但对查询表达式不太熟悉......

答案 3 :(得分:6)

我想说的主要问题是: -

  • 不安全的代码无法验证。这意味着代码只能 由用户从完全可信的上下文中运行,因此如果您需要用户从不完全信任的任何地方运行代码(例如,未配置为网络共享的网络共享)是这样),你被搞砸了。
  • 缺乏可验证性(不确定这是否真的是一个词)也意味着你可能可能搞乱程序中的内存。你可能将整个类的bug带回你的应用程序 - 缓冲区溢出,悬空指针,yada yada yuck yuck。更不用说有可能破坏内存中的数据结构而没有意识到你的指针变得奇怪了。
  • 如果您希望不安全的代码访问托管对象,则需要“固定”它们。这意味着不允许GC在内存中移动对象,因此托管堆可能会碎片化。这有性能影响;因此,确定此问题是否不会超过任何潜在的性能增益总是很重要。
  • 对于不习惯非托管方法的程序员来说,您的代码变得更难理解。然后他们可能更容易用一些“自由”不安全的代码给他们射击。
  • 您可以编写非类型安全的代码;这真的很好地消除了一个很好的温暖模糊管理语言的很多优点。现在你可以遇到可怕的类型安全问题。为什么要倒退呢?
  • 它使您的代码 uglier

我相信还有更多可以添加到列表中的内容;一般情况下,正如其他人所说的那样 - 除非你必须这样做。通过p / invoke调用非托管方法,这需要一些特殊的指针功能。即使这样,编组人员也会主要阻止对它的需要。

'男人'除非必要,否则也说避免。基本上。

哦,顺便说一下关于固定here on MSDN的好文章。

答案 4 :(得分:3)

Unsafe code是.NET CLR完全支持的功能。好处是性能和与二进制代码的兼容性。运行时是一个沙箱,可以防止崩溃和刻录,但需要付出代价。在对内存中的大blob进行极其密集的操作(例如图像处理)的情况下,超出运行时提供的正常安全性会更快。

有人说过,我认为大多数的人会说“不要这样做”。绝大多数.NET开发人员不会在正常活动中遇到只能使用不安全代码解决的案例。

答案 5 :(得分:3)

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

答案 6 :(得分:2)

如果需要,你应该使用它们;主要是在处理一些棘手的互操作场景时(例如,当我在.NET 1.0中为DPAPI编写托管包装器时,他们是需要的)但偶尔也可能通过使用{{1}来提高性能(在分析之后!)或类似的。

Microsoft建议他们尽可能多地使用C#,他们决定添加在其中编写stackalloc代码的功能。您可以从关键字的选择和描述使用关键字编写它的方法/类的要求中看到,它不是设计为事实上的实现选择。

答案 7 :(得分:2)

重新解释,就像BitConverter不提供的强制转换一样 特别是将一个unint转换为一个用于散列函数的int,其中你关心的只是位。

在结构上使用一些有用的,有充分理由的c或C ++惯用函数,你需要将它们视为众所周知的长度的字节*,同样对散列最有用。

内存结构中非常快速的二进制序列化(非常具体)(通过对它们的数组执行)虽然说实话,只需要放到C ++ / CLI就可以做得更好。

必须要说的是,在许多情况下,需要指针的任务通常可以通过在C ++ / CLI中更好地解决,然后将其作为dll导入到c#project中。它不会改变代码是否“安全”,但它使得一系列有用的函数可以更容易地在基于指针的结构上运行。如果你真的想要它,它还允许你搞乱泛型类型或枚举。

大多数开发人员需要这样做的可能性确实很小。当你需要它时很有用......

答案 8 :(得分:1)

当然它不是“推荐”,这就是它被标记为“不安全”的原因。但是不要让那吓到你。虽然,它应该让你看看你的代码两次。也许有一种管理方式可以做到这一点?

答案 9 :(得分:1)

使用不安全的代码就像忘记了.Net Framework的benenfits,我用它们一次创建了老式的结构,如堆栈和东西,但那只是为了学校,现在我还没有必要使用它们。

答案 10 :(得分:1)

如果它使您的代码更短更清晰,请执行此操作。

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