我有兴趣以重构安全的方式在运行时检索局部变量(和参数)的名称.我有以下扩展方法:
public static string GetVariableName<T>(Expression<Func<T>> variableAccessExpression)
{
var memberExpression = variableAccessExpression.Body as MemberExpression;
return memberExpression.Member.Name;
}
Run Code Online (Sandbox Code Playgroud)
...返回通过lambda表达式捕获的变量的名称:
static void Main(string[] args)
{
Console.WriteLine(GetVariableName(() => args));
// Output: "args"
int num = 0;
Console.WriteLine(GetVariableName(() => num));
// Output: "num"
}
Run Code Online (Sandbox Code Playgroud)
但是,这只能起作用,因为C#编译器将在匿名函数中捕获的任何局部变量(和参数)提升为幕后编译器生成的类中的同名实例变量(每个Jon Skeet).如果不是这种情况,则转换为Bodyto MemberExpression会失败,因为MemberExpression代表字段或属性访问.
这个变量是促销记录的行为,还是一个实现细节可能会在框架的其他版本中发生变化?
注意:这个问题是我前一个关于参数验证的概括.
根据这本在线书籍,volatileC#中的关键字不能防止重新排序Write操作,然后是Read操作.它给出了这样的例子,其中两个a和b可最终被设置为0,尽管x和y是volatile:
class IfYouThinkYouUnderstandVolatile
{
volatile int x, y;
void Test1() // Executed on one thread
{
x = 1; // Volatile write (release-fence)
int a = y; // Volatile read (acquire-fence)
...
}
void Test2() // Executed on another thread
{
y = 1; // Volatile write (release-fence)
int b = x; // Volatile read (acquire-fence)
...
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎符合10.5.3规范中的内容:
读取volatile字段称为volatile读取.易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.
写入易失性字段称为易失性写入.易失性写入具有"释放语义"; 也就是说,保证在指令序列中的写指令之前的任何存储器引用之后发生. …
以下代码中是否存在可能导致a的竞争条件NullReferenceException?
- 要么 -
Callback在空合并运算符检查空值之后但在调用函数之前,是否可以将变量设置为null?
class MyClass {
public Action Callback { get; set; }
public void DoCallback() {
(Callback ?? new Action(() => { }))();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
这是一个出于好奇而产生的问题.我通常不会这样编码.
我并不担心Callback变量变得陈旧.我担心会Exception被抛出DoCallback.
编辑#2
这是我的班级:
class MyClass {
Action Callback { get; set; }
public void DoCallbackCoalesce() {
(Callback ?? new Action(() => { }))();
}
public void DoCallbackIfElse() {
if (null != Callback) Callback();
else new Action(() => { })();
}
} …Run Code Online (Sandbox Code Playgroud) .net c# multithreading thread-safety null-coalescing-operator
编辑:我在问两个线程在没有正确同步的情况下并发访问相同数据时会发生什么(在此编辑之前,该点未明确表达).
我有一个关于C#编译器和JIT编译器执行的优化的问题.
请考虑以下简化示例:
class Example {
private Action _action;
private void InvokeAction() {
var local = this._action;
if (local != null) {
local();
}
}
}
Run Code Online (Sandbox Code Playgroud)
请在示例中忽略读取_action可能会产生缓存和过期值,因为没有volatile说明符或任何其他同步.那不是重点:)
是否允许编译器(或实际上是运行时的抖动)优化对局部变量的赋值,而是_action从内存中读取两次:
class Example {
private Action _action;
private void InvokeAction() {
if (this._action != null) {
this._action(); // might be set to null by an other thread.
}
}
}
Run Code Online (Sandbox Code Playgroud)
NullReferenceException当并行赋值将字段_action设置为时,可能会抛出一个null.
当然,在这个例子中,这样的"优化"没有任何意义,因为将值存储在寄存器中并因此使用局部变量会更快.但是在更复杂的情况下,是否可以保证无需重新读取内存中的值而按预期工作?