C# 表达式的增量值
我想写一个闭包并增加它的值,但我不能这样做。这是我的密码C# 表达式的增量值,c#,.net,reflection,code-generation,linq-expressions,C#,.net,Reflection,Code Generation,Linq Expressions,我想写一个闭包并增加它的值,但我不能这样做。这是我的密码 int i = 0; Expression<Func<bool>> closurExpression = () => { i++;
int i = 0;
Expression<Func<bool>> closurExpression = () =>
{
i++;
return i != 0;
};
我第一次意识到:
class FunctionWithCounter<T, TResult>
{
private readonly Func<T, TResult> function;
public int Calls { get; set; }
private FunctionWithCounter(Func<T, TResult> function)
{
Calls = 0;
this.function = function;
}
public static implicit operator FunctionWithCounter<T, TResult>(Func<T, TResult> func)
{
return new FunctionWithCounter<T, TResult>(func);
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg);
}
}
}
我的第二个实现是基于Emit API的,但它太复杂了,而且很长一段时间都没有完成
这是我第三次尝试,我想使用表达式。Ⅸt应如下所示:
public FunctionWithCounter(Expression<Func<T, TResult>> function)
{
Action action = () => _calls++;
Expression<Action> closurExpression = () => action();
var result = Expression.Block(closurExpression, function);
_functionWithInjection = Expression.Lambda<Func<T,TResult>>(result).Compile();
}
var rw = new RecursiveFunctionWithCounter<int, int>(
(n, self) => { return n < 2 ? 1 : n * self[n - 1]; }
);
int rr = rw[3]; // rr=6
int rc = rw.Calls; // rc=3
带计数器的公共函数(表达式函数)
{
动作动作=()=>u调用++;
表达式closurExpression=()=>action();
var result=Expression.Block(closurExpression,function);
_functionWithInjection=Expression.Lambda(result.Compile();
}
对不起,我的英语不好,但我真的很想实现这个想法。好吧,你可以使用
联锁来避开规则。增量
:
int i = 0;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
inti=0;
表达式=()=>互锁。增量(参考i)!=0;
。。。但我会非常谨慎地这样做。考虑到涉及的副作用,我不希望有很多处理表达式树的代码能够非常干净地处理这个问题
就我所期望的行为方式而言,上述措施似乎确实有效:
int i = -2;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
var del = expression.Compile();
Console.WriteLine(del()); // True
Console.WriteLine(del()); // False
Console.WriteLine(del()); // True
Console.WriteLine(del()); // True
Console.WriteLine(i); // 2
inti=-2;
表达式=()=>互锁。增量(参考i)!=0;
var del=expression.Compile();
Console.WriteLine(del());//符合事实的
Console.WriteLine(del());//错误的
Console.WriteLine(del());//符合事实的
Console.WriteLine(del());//符合事实的
Console.WriteLine(一);//2.
好吧,您可以使用联锁来避开规则。增量
:
int i = 0;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
inti=0;
表达式=()=>互锁。增量(参考i)!=0;
。。。但我会非常谨慎地这样做。考虑到涉及的副作用,我不希望有很多处理表达式树的代码能够非常干净地处理这个问题
就我所期望的行为方式而言,上述措施似乎确实有效:
int i = -2;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
var del = expression.Compile();
Console.WriteLine(del()); // True
Console.WriteLine(del()); // False
Console.WriteLine(del()); // True
Console.WriteLine(del()); // True
Console.WriteLine(i); // 2
inti=-2;
表达式=()=>互锁。增量(参考i)!=0;
var del=expression.Compile();
Console.WriteLine(del());//符合事实的
Console.WriteLine(del());//错误的
Console.WriteLine(del());//符合事实的
Console.WriteLine(del());//符合事实的
Console.WriteLine(一);//2.
我认为您的第一种方法对于简单的、非递归的情况来说更干净、更合适。
如果您允许您的包装函数意识到递归,那么您可以更进一步,使包装函数成为函数本身的参数:
class RecursiveFunctionWithCounter<T, TResult>
{
private readonly Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function;
public int Calls { get; set; }
public RecursiveFunctionWithCounter(Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function)
{
Calls = 0;
this.function = function;
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg, this);
}
}
}
使用计数器初始化递归函数
{
私有只读函数;
公共int调用{get;set;}
带计数器的公共递归函数(Func函数)
{
调用=0;
这个函数=函数;
}
public TResult this[T arg]
{
收到
{
调用++;
返回函数(arg,this);
}
}
}
然后像这样使用它:
public FunctionWithCounter(Expression<Func<T, TResult>> function)
{
Action action = () => _calls++;
Expression<Action> closurExpression = () => action();
var result = Expression.Block(closurExpression, function);
_functionWithInjection = Expression.Lambda<Func<T,TResult>>(result).Compile();
}
var rw = new RecursiveFunctionWithCounter<int, int>(
(n, self) => { return n < 2 ? 1 : n * self[n - 1]; }
);
int rr = rw[3]; // rr=6
int rc = rw.Calls; // rc=3
var rw=带计数器的新递归函数(
(n,self)=>{returnn<2?1:n*self[n-1];}
);
int rr=rw[3];//rr=6
int rc=rw.Calls;//rc=3
另一方面,如果您真正想要做的是在代码中检测一些现有的方法,那么请考虑做一点(例如,这是在每个方法调用上增加性能计数器的一个方面)。通过这种方式,您可以在方法中添加一个属性,如
IncrementPerformanceCounterAttribute
,AOT库将完成其余的工作。我认为您的第一种方法更简洁,适用于简单、非递归的情况。
如果您允许您的包装函数意识到递归,那么您可以更进一步,使包装函数成为函数本身的参数:
class RecursiveFunctionWithCounter<T, TResult>
{
private readonly Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function;
public int Calls { get; set; }
public RecursiveFunctionWithCounter(Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function)
{
Calls = 0;
this.function = function;
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg, this);
}
}
}
使用计数器初始化递归函数
{
私有只读函数;
公共int调用{get;set;}
带计数器的公共递归函数(Func函数)
{
调用=0;
这个函数=函数;
}
public TResult this[T arg]
{
收到
{
调用++;
返回函数(arg,this);
}
}
}
然后像这样使用它:
public FunctionWithCounter(Expression<Func<T, TResult>> function)
{
Action action = () => _calls++;
Expression<Action> closurExpression = () => action();
var result = Expression.Block(closurExpression, function);
_functionWithInjection = Expression.Lambda<Func<T,TResult>>(result).Compile();
}
var rw = new RecursiveFunctionWithCounter<int, int>(
(n, self) => { return n < 2 ? 1 : n * self[n - 1]; }
);
int rr = rw[3]; // rr=6
int rc = rw.Calls; // rc=3
var rw=带计数器的新递归函数(
(n,self)=>{returnn<2?1:n*self[n-1];}
);
int rr=rw[3];//rr=6
int rc=rw.Calls;//rc=3
另一方面,如果您真正想要做的是在代码中检测一些现有的方法,那么请考虑做一点(例如,这是在每个方法调用上增加性能计数器的一个方面)。通过这种方式,您只需在方法中添加一个属性,如
IncrementPerformanceCounterAttribute
,AOT库就会完成其余的工作。您实际上想要实现什么?我已经给出了一个答案,但实际上这是一个绕过编译器的确切规则,同时仍然违反这些规则精神的例子。你到底想达到什么目的?我已经给出了一个答案,但它实际上是绕过编译器的确切规则,同时仍然违反这些规则的精神。至少,它是有效的(与我的解决方案不同)。如果不考虑性能,这是非常好的。关于AOP的内容:我不想对外部代码使用任何属性,所有事情都应该在这个类的内部完成。对于用户来说,除了附加的字段调用和foo[x]
concept而不是foo(x)
,它不应该与简单的委托不同。也许,Rosylin后处理可以帮助我,但它没有做到至少,它是有效的(不像我的解决方案)。如果不考虑性能,这是非常好的。关于AOP的内容:我不想对外部代码使用任何属性,所有事情都应该在这个类的内部完成。对于用户来说,除了附加的字段调用和foo[x]
concept而不是foo(x)
,它不应该与简单的委托不同。也许,Rosylin后处理可以帮我,但它还没有完成