在循环内部或外部使用 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 有啥区别吗?的主要内容,如果未能解决你的问题,请参考以下文章

block在arc中和mrc中的用法有啥区别

Solidity 中的内部/外部和公共/私人功能有啥区别?

在循环体外面定义的变量和里面定义的变量有啥区别?

sizeof(T) 和 Unsafe.SizeOf<T>() 有啥区别?

Thread.State: WAITING (parking) vs BLOCKED at sun.misc.Unsafe.park() 有啥区别

内存条有啥用