添加到方法组是否计为使用变量?

时间:2011-02-14 22:43:29

标签: c# resharper

我从Form的代码中获取了以下代码示例:

    protected void SomeMethod()
    {
        SomeOtherMethod(this.OnPaint);
    }

    private void SomeOtherMethod(Action<PaintEventArgs> onPaint)
    {
        onPaint += MyPaint;
    }

    protected void MyPaint(PaintEventArgs e)
    {
        // paint some stuff
    }

第二种方法(SomeOtherMethod)有一个resharper抱怨我。它说onPaint “分配的值未在任何执行路径中使用”

在我看来它是被使用的,因为我在绘制完成时调用的方法列表中添加了一个方法。

但通常当resharper告诉我这样的事情是因为我不理解C#的某些部分。就像当参数超出范围时,我添加到列表中的项目将被删除(或类似的东西)。

我想我会问这里是否有人知道resharper试图告诉我什么。

(旁注:我通常只是重写OnPaint。但是我试图让OnPaint在另一个类中调用一个方法。我不想公开公开该方法,所以我想我会传入OnPaint组并添加它。)

5 个答案:

答案 0 :(得分:8)

警告是正确的。请考虑以下事项:

int X;
int Y;
void SomeMethod()
{         
    SomeOtherMethod(this.X);
}      
void SomeOtherMethod(int x)
{
    x += this.Y;
}

这里代码修改形式参数x,然后从不使用修改过的x。这不会修改“this.X”

你和代表做了同样的事情。您修改形式参数,然后从不使用结果;原始的“OnPaint”没有变化,就像我的例子中“X”没有变化一样。

请记住,仅仅因为委托是引用类型并不意味着当您传递实例时,您正在传递对变量的引用。您正在传递对实例的引用,而不是对该实例的存储位置的引用。

答案 1 :(得分:5)

它有用吗?我不指望MyPaint会被调用。那将是一个线索。

在我看来,onPaint += MyPaint;在此方法之外没有任何影响。 onPaint是一个参数(局部变量),当方法退出时,更改将丢失。这就是你得到警告的原因。

要了解原因,您需要类似ref参数的内容,但不能使用事件(this.Onpaint)调用它:

// not applicable
private void SomeOtherMethod(ref Action<PaintEventArgs> onPaint)
{
   onPaint += MyPaint;
}

答案 2 :(得分:5)

委托是不可变的,因此组合创建副本。当你打电话:

private void SomeOtherMethod(Action<PaintEventArgs> onPaint)

您实际上是在创建原始Action<PaintEventArgs>的修改过的副本

话虽这么说,我个人会避免尝试这种方式,除非有一个非常令人信服的理由这样做。

就个人而言,我会考虑创建一个公开OnPaint事件的接口,并将接口传递给此方法。然后,您可以订阅该活动。这会产生与你想要达到的效果相同的效果,但要更清楚。

在这种情况下,我会让你的另一个类直接订阅Control上的Paint event

答案 3 :(得分:5)

代表是不可变的。你无法改变它们。在这方面他们有点像弦乐。想象一下你的方法是:

private void SomeOtherMethod(string x)
{
    x += "hello";
}

同样,这将是一个毫无意义的方法。原始字符串不会改变 - 您只是更改了局部变量(参数)的值以引用不同的字符串。在你的委托案件中也会发生同样的事情。

要么你需要通过引用传递变量,你需要改变整个设计。

有关委托合并的工作原理,请参阅我在delegates and events上的文章。

答案 4 :(得分:2)

在做了一些实验之后,我认为原因是当你在+=上进行Action时,你不是在修改初始值,而是修改局部变量本身。例如:

void Main()
{
    Action<int> doSomething = OnClick;
    doSomething += i=> Console.WriteLine("test");
    OnClick(1);
}

private void OnClick(int i)
{
    Console.WriteLine("clicked");
}

...只是产生“点击”。

因此,您的示例中的MyPaint方法未被修改,只有onPaint变量。由于您在+=之后没有对该变量执行任何操作,因此首先执行+=毫无意义。

修改

Porges指出,由于OnClick是一种方法(不是委托),因此这个例子不太准确。这是一个更好的:

Action<int> doSomething = i => Console.WriteLine("test");
var doSomething2 = doSomething; 
doSomething2 += i => Console.WriteLine("test2");
doSomething(1);

输出:test