我理解指针,并且很少需要在C#代码中使用它们。我的问题是:在一段代码中明确说明“不安全”的原因是什么。另外,为什么必须更改编译器选项以允许“不安全”代码?
底线: CLR(或语言规范)中的内容使得我们不能随时使用指针(很像C和C ++)而不必输入“unsafe”和更改编译器选项?
澄清:我知道“不安全”和“安全”的代码是什么。这只是一个问题,为什么我们必须做所有额外的工作(好吧,不要多得多)只是为了能够使用这些功能。
答案 0 :(得分:9)
接受了C#Creator Anders Hejlsberg的采访,涉及主题here。基本上,正是@Marc Gravell所说的:首先是类型安全,通过明确声明不安全。
所以回答你的问题:CLR中没有任何东西阻止它;它是一种语言习语,旨在让您在处理类型时使用安全手套。如果你想脱下手套,这是你的选择,但你必须做出积极的选择才能脱下手套。
修改强>
澄清:我知道什么 “不安全”和“安全”的代码是。只是 我们为什么要做所有这一切的问题 额外的工作(好吧,不是多多额外的) 只是为了能够使用这些功能。
正如我所接受的采访中提到的,这是一个明确的设计决定。 C#本质上是Java的演变,在Java中,你根本就没有指针。但设计师想要指点;但是因为C#通常会引入Java开发人员,他们认为如果默认行为与Java类似,即没有指针,同时仍允许通过显式声明使用指针,那将是最好的。
所以“额外的工作”是故意强迫你在做之前考虑你在做什么。通过明确,它迫使你至少考虑:“为什么我这样做?当参考类型足够时,我真的需要指针吗?”
答案 1 :(得分:7)
主要是关于可验证的。通过陈述unsafe
,手套关闭 - 系统无法保证您的代码不会无法正常运行。在大多数情况下,非常希望留在安全区。
使用部分信任(插件等)会更加明显,但在常规代码中仍然很有价值。
答案 2 :(得分:3)
实际上,CLR对/ unsafe开关或关键字没有任何要求。事实上,C ++ / CLI(在CLR下运行的C ++语言)没有这样/不安全的开关,并且指针可以在CLR上自由使用。
所以我将你的问题改为“为什么C#在使用指针之前需要使用/ unsafe?”这个问题的答案如此处给出的其他答案中所述:帮助用户有意识地决定失去在CLR上以低于完全信任模式运行的能力。 C ++几乎总是需要CLR上的完全信任,并且只要您调用需要完全信任的代码,或者无论何时使用指针,C#都可以。
答案 3 :(得分:2)
当您使用不安全的块时,它会使代码无法验证。这需要执行某些权限,您可能不希望在输出中允许它(特别是如果您在共享源环境中),因此编译器中有一个禁止它的开关。
答案 4 :(得分:2)
从相反的角度考虑:因为它没有被标记为不安全,所以你可以推断大多数代码默认是“安全的”。那么“安全”是什么意思呢?对于.Net代码,这包括(但可能不限于):
任何时候你使用指针你都有机会打破任何这些保证。因此,将代码标记为不安全会放弃这些保护措施。
答案 5 :(得分:2)
简而言之,.NET希望您说明您的意图。
当然,编译器可以推断出对“不安全”标志的需求。但设计师希望这是一个慎重的决定。
对我而言,它类似于C#中的一些语法要求:
模式是你不应该移动或改变一件事而无意中影响另一件事。在合理的范围内,他们希望阻止你“自己在脚下射击。”
这里有很多很好的,信息丰富的答案 - 也许这更适合你的问题。
答案 6 :(得分:1)
因此,很明显,如果没有提升权限等,哪些代码将无法在Web服务中运行。
答案 7 :(得分:1)
养成良好的习惯&安全。每当在程序集中使用不安全的块时,都会从堆栈中请求NativeCode权限。这当然可以隐式完成,但我们不能完全删除private关键字吗?我认为强迫开发人员在使用之前专门要求不安全的代码是好的。
答案 8 :(得分:1)
安全和不安全代码之间最显着的区别是.net的垃圾收集器无法访问不安全的代码。自动GC是.net白话的一个重要组成部分,当你超越它的界限时,你会改变很多关于代码的假设。
指针特别允许在堆上创建没有GC引用的对象。这导致另一个很好的理由要求将代码标记为“不安全”。当您意识到有内存泄漏时,可以轻松缩小内存泄漏的范围。