C#:明确声明“不安全”的好处 / 编译器选项

发布于 2024-07-14 14:49:52 字数 282 浏览 11 评论 0原文

我了解指针以及在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

无需解释 2024-07-21 14:49:52

这里有一篇对 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:

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.

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?"

千仐 2024-07-21 14:49:52

这主要是为了可验证。 通过声明不安全,手套就脱掉了——系统无法再保证您的代码不会失控。 在大多数情况下,非常希望留在安全区。

这在部分信任(插件等)中变得更加明显,但在常规代码中仍然很有价值。

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.

风蛊 2024-07-21 14:49:52

实际上,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.

别想她 2024-07-21 14:49:52

当您使用不安全的块时,它会导致代码无法验证。 这需要一定的权限才能执行,并且您可能不希望在输出中允许它(尤其是在共享源环境中),因此编译器中有一个开关可以禁止它。

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.

死开点丶别碍眼 2024-07-21 14:49:52

从相反的角度思考:因为它没有被标记为不安全,所以您可以推断大多数代码默认情况下是“安全”的。 那么“安全”是什么意思呢? 对于 .Net 代码,这包括(但可能不限于):

  • 垃圾收集器可以照常工作。
  • 对特定类型的引用将引用该类型(或 null)的对象。
  • 保证代码符合.Net 信任/安全要求。
  • 该代码经过数学证明不会直接接触其自己的 AppDomain 之外的内存。 这可能看起来微不足道,但想象一下如果您在同一个应用程序中有多个 AppDomain。 程序员可以自信地将它们视为逻辑上独立的。

任何时候你使用指针,你都有机会打破这些保证。 因此,将代码标记为不安全就放弃了这些保护。

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):

  • The garbage collector can do business as usual.
  • References to a specific type will refer to objects of that type (or null).
  • Code is guaranteed to comply with .Net trust/security requirements.
  • The code is mathematically proven not to directly touch memory outside it's own AppDomain. It may seem trivial, but imagine if you have multiple AppDomains in the same application. The programmer can confidently treat them as logically separate.

Any time you use pointers you have the chance to break any of those guarantees. Therefore marking code as unsafe gives up those protections.

£噩梦荏苒 2024-07-21 14:49:52

简而言之,.NET 希望您陈述您的意图。

当然,编译器可以推断出需要“不安全”标志。 但设计师希望这是一个经过深思熟虑的决定。

对我来说,它类似于 C# 中的许多语法要求:

  • 没有不带中断的 switch case
  • 没有访问级别“部分”(例如 C++ 中的“public:”标记)
  • 没有使用“var”的类字段

模式是您不应移动或改变一件事而无意中影响另一件事。 在合理范围内,他们希望阻止你“搬起石头砸自己的脚”。

这里有很多很棒的、内容丰富的答案——也许这更符合你的问题。

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#:

  • no switch case without break
  • no access-level "sections" (such as the "public:" marker in C++)
  • no class fields using "var"

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.

归途 2024-07-21 14:49:52

这样,如果没有提升的权限等,哪些代码将无法在 Web 服务中运行是显而易见的。

So that it is immediately obvious which code won't run in web services without elevated permissions, etc.

静水深流 2024-07-21 14:49:52

培养良好习惯& 安全。 每当您在程序集中使用不安全的块时,都会向堆栈请求 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.

别把无礼当个性 2024-07-21 14:49:52

安全代码和不安全代码之间最显着的区别是.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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文