使用 unsafe 关键字在循环内部和外部有什么区别吗?

65

过去我从来没有需要使用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.
        }
    }
}

3
考虑到 for 循环本身不需要 unsafe,你可能会认为做第二个更好,并且您希望将 unsafe 区域最小化。除非在循环调用时存在某种开销。 - AustinWBryan
根据我所阅读的,似乎你是正确的,这也是我们正在做的事情,但我想更好地理解其中的区别。 - Dzyann
@Dzyann 看起来不是一道容易回答的问题..你可能需要耐心等待.. ;) 我也很想知道解释。 - Ian
1
我非常怀疑在生成的代码方面是否有任何区别。主要的区别将是减少代码中“不安全”部分的占用空间。为什么在不安全块中包含更多内容?这只会创建额外的代码行,使您可以在规范之外犯错误。 - Glorin Oakenfoot
3
我认为第一个代码块会让人们感到困惑,并让他们想知道为什么循环是“不安全”的。 - Drew Kennedy
2个回答

56

unsafe 关键字是一个标记,你可以使用它来告诉编译器,你知道自己在做什么。它的主要目的类似于文档化你的代码:unsafe 块显示你指定为未经管理的领域的代码部分;但实际上对代码的 执行 没有影响。

基于这一点,将不安全区域的大小尽可能减小是有意义的,这意味着你的第二种方法比第一种更好。

值得注意的是,另外两种选择,即标记方法和标记类为 unsafe,也不如当 unsafe 块放置在尽可能小的代码部分时的方法。


37

unsafe 改变编译器接受和产生输出的表达式。它本身不会带来运行时开销。对于任何不需要 unsafe 的表达式,无论其是否在 unsafe 上下文中,编译器都会生成相同的代码。

关于只能在 unsafe 上下文中使用哪些表达式的具体信息,建议查阅C#语言规范的第18节。


4
针对不可避免的评论,声称这并没有回答问题:考虑到这个问题在StackOverflow上是不相关的,所以这个回答尽可能接近问题的回答。如果你想获得设计建议而不仅仅是技术建议,请尝试CodeReview.SE。 - Luaan
1
@Luaan - 感谢您指出这一点。我并不认为这是设计建议,因为我已经剥离了问题中的实际设计代码。我的兴趣在于了解unsafe的工作方式,因为我搜索了一下,但并不清楚。 - Dzyann
9
不,它并没有回答问题。这个问题是否处于 SO 和 CR 之间的边界?是的。这是否意味着它不能在 SO 上?我不这么认为,但如果你认为是的,你应该投票将其关闭为 off-topic。但是,对于这个问题的任何答案都必须回答这个问题,而这个答案并没有做到。给出一个半回答并不是认为一个问题不属于范围的适当回应;将其迁移投票才是。 - KRyan
1
@KRyan 嗯,你看了答案吗?它基本上说“这两个产生完全相同的字节码”。你认为什么样的答案更合适呢? - Luaan
2
@KRyan - 它的目的是改变编译器将接受和生成输出的内容。这实际上是我回答的第一句话。 - Damien_The_Unbeliever
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接