在循环内部或外部使用 unsafe 有啥区别吗?
Posted
技术标签:
【中文标题】在循环内部或外部使用 unsafe 有啥区别吗?【英文标题】:Does it make any difference to use unsafe inside or outside a loop?在循环内部或外部使用 unsafe 有什么区别吗? 【发布时间】:2016-04-29 04:00:06 【问题描述】:过去我从来不需要使用 unsafe,但现在我需要它来使用指针来操作位图。
我找不到任何说明其他情况的文档,但我想更好地了解 unsafe 的工作原理以及在循环内部或外部使用它是否有任何区别。
这样做更好吗:
unsafe
for (int x = 0; x < maxX; x++)
for (int y = 0; y < maxY; y++)
//Unsafe pointer operations here.
还是要做什么?:
for (int x = 0; x < maxX; x++)
for (int y = 0; y < maxY; y++)
unsafe
//Unsafe pointer operations here.
【问题讨论】:
我认为最好做第二个,考虑到 for 循环本身不需要是unsafe
并且您希望最小化 unsafe
区域。除非,在循环中调用它会产生某种开销。
@AustinWBryan - 根据我的阅读,您似乎是对的,这就是我们正在做的,但我想更好地了解有什么区别。
@Dzyann 似乎不是一个容易回答的问题.. 你可能需要耐心等待.. ;) 我也有兴趣知道解释
我非常怀疑生成的代码有什么不同。主要区别在于减少代码的unsafe
占用空间。为什么在 unsafe 块中包含超出您需要的内容?它只是创建了额外的代码行,您可以在其中犯超出规范的错误。
我认为第一段代码会让人们感到困惑,让他们想知道为什么循环是unsafe
。
【参考方案1】:
unsafe
关键字是一个标记,用于告诉编译器您知道自己在做什么。其主要目的类似于记录您的代码:unsafe
块显示您指定为非托管区域的部分代码;对代码的实际执行没有影响。
考虑到这一点,尽可能减小这个不安全区域的大小是有意义的,这意味着您的第二种方法比第一种方法更好。
值得一提的是,另外两个替代方案,即用unsafe
标记方法和标记类,也不如将不安全块放置在代码的尽可能小的部分周围的方法。
【讨论】:
【参考方案2】:unsafe
更改编译器将接受并为其生成输出的表达式。它本身不强加运行时开销。对于不需要unsafe
的任何表达式,无论是否在unsafe
上下文中,编译器都会发出相同的代码。
对于哪些表达式只能在unsafe
上下文中使用的细节,我建议参考C# Language Specification的第18节
【讨论】:
对于那些说这不能回答问题的不可避免的 cmets:考虑到这个问题在 *** 上是题外话,这尽可能接近回答问题。 @Dzyann 如果您需要设计建议,而不仅仅是技术建议,请尝试 CodeReview.SE。 @Luaan - 感谢您指出这一点。我并不认为这是设计建议,因为我已经剥离了关于我们实际设计问题的代码。我的兴趣是 unsafe 的工作方式,因为我四处寻找,但我并不清楚。 @Luaan 不,它没有回答这个问题。问题是否介于 SO 和 CR 之间?是的。这是否意味着它不能在SO上?我不这么认为,但如果你这样做,你应该投票将其作为离题关闭。但是对问题的任何回答都必须回答问题,而事实并非如此。给出一个半答案并不是对认为问题偏离主题的适当回应;投票迁移它。 @KRyan 嗯,你读过答案了吗?它基本上说“两者产生完全相同的字节码”。您认为哪种答案更合适? @KRyan - 其目的是更改编译器将 接受 并产生输出的内容。这是我回答的第一句话。以上是关于在循环内部或外部使用 unsafe 有啥区别吗?的主要内容,如果未能解决你的问题,请参考以下文章
sizeof(T) 和 Unsafe.SizeOf<T>() 有啥区别?
Thread.State: WAITING (parking) vs BLOCKED at sun.misc.Unsafe.park() 有啥区别