C#:明确声明“不安全”的好处 / 编译器选项
我了解指针以及在 C# 代码中使用它们的罕见需求。 我的问题是:必须在代码块中明确声明“不安全”背后的原因是什么。 此外,为什么必须更改编译器选项以允许“不安全”代码?
底线: CLR(或语言规范)中的内容使得我们不能随心所欲地使用指针(很像 C 和 C++),而不必键入“不安全”并更改编译器选项?
澄清一下:我知道什么是“不安全”和“安全”代码。 这只是一个问题,为什么我们必须做所有额外的工作(好吧,不是那么多额外的工作)才能使用这些功能。
I understand pointers and the rare need to use them in C# code. My question is: what is the reasoning behind having to explicitly state "unsafe" in a block of code. Additionally, why must a compiler option be changed to allow "unsafe" code?
Bottom Line: What in the CLR (or language specs) makes it so we can't just use pointers whenever we want (much like C and C++) without having to type "unsafe" and change the compiler option?
For clarification: I know what "unsafe" and "safe" code is. It's just a question of why must we do all the extra work (ok, not THAT much extra) just to be able to use these features.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这里有一篇对 C# 创建者 Anders Hejlsberg 的采访,内容涉及该主题< /a>. 基本上,正如 @Marc Gravell 所说:类型安全第一,显式声明不安全。
所以回答你的问题:CLR 中没有任何东西可以阻止它; 这是一种语言习语,旨在让您在处理类型时能够戴着安全手套。 如果你想脱掉手套,那是你的选择,但你必须主动选择脱掉手套。
编辑:
正如我链接的采访中提到的,这是一个明确的设计决策。 C# 本质上是 Java 的演变,而在 Java 中,根本没有指针。 但设计者希望允许指针; 然而,由于 C# 通常会引入 Java 开发人员,因此他们认为最好的方式是默认行为与 Java 类似,即没有指针,同时仍然允许通过显式声明使用指针。
所以“额外的工作”是故意强迫你在做之前思考你在做什么。 通过明确,它迫使您至少考虑:“我为什么要这样做?当引用类型就足够了时,我真的需要一个指针吗?”
There's an interview with C# Creator Anders Hejlsberg that touches on the subject here. Basically, exactly what @Marc Gravell said: typesafety first, unsafety by explicit declaration.
So to answer your question: nothing in the CLR prevents it; it's a language idiom designed to allow you to work with safety gloves when dealing with types. If you want to take the gloves off, it's your choice, but you have to make the active choice to take the gloves off.
Edit:
As mentioned in the interview I linked, it was an explicit design decision. C# is essentially an evolution of Java and in Java, you don't have pointers at all. But the designers wanted to allow pointers; however because C# would typically be bringing in Java developers, they felt it would be best if the default behavior be similar to Java, i.e. no pointers, while still allowing the use of pointers by explicit declaration.
So the "extra work" is deliberate to force you to think about what you are doing before you do it. By being explicit, it forces you to at least consider: "Why am I doing this? Do I really need a pointer when a reference type will suffice?"
这主要是为了可验证。 通过声明
不安全
,手套就脱掉了——系统无法再保证您的代码不会失控。 在大多数情况下,非常希望留在安全区。这在部分信任(插件等)中变得更加明显,但在常规代码中仍然很有价值。
It is largely about being verifiable. By stating
unsafe
, the gloves are off - the system can no longer guarantee that your code won't run amok. In most cases it is highly desirable to stay in the safe zone.This gets more noticeable with partial trust (addins etc), but is still valuable in regular code.
实际上,CLR 对 /unsafe 开关或关键字没有任何要求。 事实上,C++/CLI(运行在CLR下的C++语言)没有这样的/unsafe开关,指针可以在CLR上自由使用。
因此,我会将您的问题改写为“为什么 C# 需要在使用指针之前使用 /unsafe?” 该问题的答案如此处给出的其他答案所述:帮助用户做出有意识的决定,失去在 CLR 上以非完全信任模式运行的能力。 C++ 实际上总是需要 CLR 上的完全信任,而每当您调用需要完全信任的代码或使用指针时,C# 都可以。
Actually the CLR makes no requirements at all about an /unsafe switch or keyword. In fact, C++/CLI (the C++ language that runs under the CLR) has no such /unsafe switch, and pointers can be used freely on the CLR.
So I would rephrase your question as "Why does C# require the use of /unsafe before pointers can be used?" And the answer to that question is as stated in other answers given here: to help the user make a conscious decision to lose the ability to run in anything less than Full Trust mode on the CLR. C++ virtually always requires Full Trust on the CLR, and C# can whenever you call code that requires Full Trust, or whenever you use pointers.
当您使用不安全的块时,它会导致代码无法验证。 这需要一定的权限才能执行,并且您可能不希望在输出中允许它(尤其是在共享源环境中),因此编译器中有一个开关可以禁止它。
When you use an unsafe block, it has the effect of making the code unverifiable. This requires certain permissions to execute and you might not want to allow it in your output (especially if you are in a shared source environment), so there is a switch in the compiler to disallow it.
从相反的角度思考:因为它没有被标记为不安全,所以您可以推断大多数代码默认情况下是“安全”的。 那么“安全”是什么意思呢? 对于 .Net 代码,这包括(但可能不限于):
任何时候你使用指针,你都有机会打破这些保证。 因此,将代码标记为不安全就放弃了这些保护。
Think about it from the opposite point of view: because it's not marked unsafe, you can infer that most code is "safe" by default. So what does it mean to be "safe"? For .Net code, this includes (but may not be limited to):
Any time you use pointers you have the chance to break any of those guarantees. Therefore marking code as unsafe gives up those protections.
简而言之,.NET 希望您陈述您的意图。
当然,编译器可以推断出需要“不安全”标志。 但设计师希望这是一个经过深思熟虑的决定。
对我来说,它类似于 C# 中的许多语法要求:
模式是您不应移动或改变一件事而无意中影响另一件事。 在合理范围内,他们希望阻止你“搬起石头砸自己的脚”。
这里有很多很棒的、内容丰富的答案——也许这更符合你的问题。
In short, .NET wants you to state your intent.
Sure, the compiler could infer the need for the "unsafe" flag. But the designers want it to be a deliberate decision.
To me, it's akin to a number of syntactic requirements in C#:
The pattern is that you shouldn't move or change one thing and inadvertently affect another. Within reason, they want to keep you from "shooting yourself in the foot."
Lots of great, informative answers here — maybe this goes more to your question.
这样,如果没有提升的权限等,哪些代码将无法在 Web 服务中运行是显而易见的。
So that it is immediately obvious which code won't run in web services without elevated permissions, etc.
培养良好习惯& 安全。 每当您在程序集中使用不安全的块时,都会向堆栈请求 NativeCode 权限。 这当然可以隐式完成,但是我们不能完全删除 private 关键字吗? 我认为强制开发人员在使用不安全代码之前明确要求它是件好事。
Nurturing good habits & security. Whenever you use an unsafe block in an assembly, a NativeCode permission will be demanded from the stack. This could of course be done implicitly, but couldn't we also just remove the private keyword completely? I think it's good to force developers to specifically require unsafe code before they can use it.
安全代码和不安全代码之间最显着的区别是.net 的垃圾收集器无法访问不安全代码。 自动 GC 是 .net 语言的重要组成部分,当您超出其边界时,您会更改许多关于代码的假设。
指针特别允许在堆上创建没有 GC 引用的对象。 这导致了要求将代码标记为“不安全”的另一个极好的理由。 当您意识到存在内存泄漏时,可以轻松缩小内存泄漏的范围。
The most significant difference between safe and unsafe code is that unsafe code is unreachable by .net's garbage collector. Automatic GC is a huge part of the vernacular of .net and, when you go beyond its boundaries, you change a lot of what can be assumed about your code.
Pointers in particular allow for the creation of objects on the heap with no GC references. This leads to another excellent reason to require code to be marked as "unsafe." It makes it easy to narrow down where a memory leak is coming from when you realize you have one.