AsV*_*leO 11 c# foreach increment thread-safety interlocked-increment
最近我从VB转到C#,所以我经常使用C#到VB.NET转换器来理解语法差异.在将下一个方法移动到VB时,我发现了一个有趣的事情
C#原始代码:
public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
{
int trueCnt = 0;
foreach(bool b in bools)
if (b && (++trueCnt > threshold))
return true;
return false;
}
Run Code Online (Sandbox Code Playgroud)
VB.NET结果:
Public Function ExceedsThreshold(threshold As Integer, bools As IEnumerable(Of Boolean)) As Boolean
Dim trueCnt As Integer = 0
For Each b As Boolean In bools
If b AndAlso (System.Threading.Interlocked.Increment(trueCnt) > threshold) Then
Return True
End If
Next
Return False End Function
Run Code Online (Sandbox Code Playgroud)
C#的++
运算符被替换为System.Threading.Interlocked.Increment
是否意味着++
如果在foreach
循环中使用,线程安全运算符不会成为线程安全的?它是一种语法糖吗?如果这是真的,那么为什么转换器放在Interlocked.Increment
VB版本中?我认为C#和VB中的foreach完全相同.或者它只是一个转换器"保险"?
Luc*_*ski 11
我确定它只是一个转换器黑客,我想我可以解释这背后的原因.
但首先,只是回答你的问题,++
C#中的内置运算符不是线程安全的.它只是以下过程的语法糖(在这种情况下++i
):
i
i
由于存在单独的读写,因此这是非原子操作.
现在,在VB中没有直接等效的++
运算符.最接近的是:
i += 1
Run Code Online (Sandbox Code Playgroud)
但这是一个声明.相比之下,++i
是一种表达方式.您可以++i
在另一个语句或表达式中使用,但不能使用VB语句.
使用Interlocked.Increment
只是一种轻松翻译代码的聪明方法,而不必将整个语句分解为多个其他语句.
如果没有这个技巧,转换器必须像这样分解表达式:
if (b && (++trueCnt > threshold))
...
Run Code Online (Sandbox Code Playgroud)
If b Then
trueCnt += 1
If trueCnt > threshold Then
...
End If
End If
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这需要更多的重写.如果trueCnt
是属性,它甚至需要引入一个单独的临时变量(以避免对它进行两次评估).
这需要更深层次的语义分析和控制流重写比简单句法转换器的使用-只是因为trueCnt += 1
不能使用内部在VB中的表达.
归档时间: |
|
查看次数: |
534 次 |
最近记录: |