我从以下代码中获取以下代码示例Form
:
protected void SomeMethod()
{
SomeOtherMethod(this.OnPaint);
}
private void SomeOtherMethod(Action<PaintEventArgs> onPaint)
{
onPaint += MyPaint;
}
protected void MyPaint(PaintEventArgs e)
{
// paint some stuff
}
Run Code Online (Sandbox Code Playgroud)
第二种方法(SomeOtherMethod
)有resharper向我抱怨.它说的onPaint
是"分配的任何执行路径没有使用的价值".
在我看来它被使用是因为我在绘制完成时调用的方法列表中添加了一个方法.
但通常当resharper告诉我这样的事情是因为我不理解C#的某些部分.就像当参数超出范围时,我添加到列表中的项目将被删除(或类似的东西).
我想我会问这里是否有人知道重塑者试图告诉我什么.
(旁注:我通常只是重写OnPaint.但我试图让OnPaint在另一个类中调用一个方法.我不想公开公开该方法,所以我想我会传入OnPaint组并添加它. )
警告是正确的.考虑以下:
int X;
int Y;
void SomeMethod()
{
SomeOtherMethod(this.X);
}
void SomeOtherMethod(int x)
{
x += this.Y;
}
Run Code Online (Sandbox Code Playgroud)
这里代码修改形式参数x,然后从不使用修改后的x.这不会修改"this.X"
你和代表做了同样的事情.您修改形式参数,然后从不使用结果; 原始的"OnPaint"没有变化,就像我的例子中"X"没有变化一样.
请记住,仅仅因为委托是引用类型并不意味着在传递实例时传递对变量的引用.您正在传递对实例的引用,而不是对该实例的存储位置的引用.
它有用吗?我不指望MyPaint会被调用.这将是一个线索.
在我看来,onPaint += MyPaint;
这种方法之外没有任何影响.onPaint
是一个参数(局部变量),当方法退出时,更改将丢失.这就是你得到警告的原因.
要知道原因,你需要像ref
参数这样的东西,但你不能用事件调用它(this.Onpaint):
// not applicable
private void SomeOtherMethod(ref Action<PaintEventArgs> onPaint)
{
onPaint += MyPaint;
}
Run Code Online (Sandbox Code Playgroud)
代理是不可变的,因此组合创建一个副本.你打电话的时候:
private void SomeOtherMethod(Action<PaintEventArgs> onPaint)
Run Code Online (Sandbox Code Playgroud)
您实际上正在创建原始的修改副本Action<PaintEventArgs>
.
话虽如此,我个人会避免尝试这种方式,除非有一个非常令人信服的理由这样做.
就个人而言,我会考虑创建一个公开OnPaint
事件的接口,并将接口传递给此方法.然后,您可以订阅该活动.这会产生与你想要达到的效果相同的效果,但要清楚得多.
在这种情况下,我会让你的其他类直接在Control上订阅Paint事件.
代表是不可改变的.你无法改变它们.在这方面他们有点像弦乐.想象一下你的方法是:
private void SomeOtherMethod(string x)
{
x += "hello";
}
Run Code Online (Sandbox Code Playgroud)
同样,这将是一个毫无意义的方法.原始字符串不会改变 - 您只是更改了局部变量(参数)的值以引用不同的字符串.在你的委托案件中发生了完全相同的事情.
无论你需要按引用传递变量或者你需要改变你的整个设计.
有关委托组合如何工作的更多信息,请参阅我关于委托和事件的文章.