Does adding to a group of methods make use of a variable?

I have the following code sample taken from Form code:

  protected void SomeMethod() { SomeOtherMethod(this.OnPaint); } private void SomeOtherMethod(Action<PaintEventArgs> onPaint) { onPaint += MyPaint; } protected void MyPaint(PaintEventArgs e) { // paint some stuff } 

The second method ( SomeOtherMethod ) has a reporter complaining about me. He says onPaint that "the assigned value is not used in any execution path."

In my opinion, this was used because I added the method to the list of methods that were called when the paint was done.

But usually when resharper tells me something like this, it is because I don’t understand some part of C #. How is it possible, when a parameter leaves the region leaves the region, the element that I added to the list is deleted (or something like that).

I thought I would ask here to see if anyone knows what the Reshar is trying to tell me.

(Side Note: I usually just override OnPaint, but I try to get OnPaint to call the method in another class. I don’t want to publish this method publicly, so I thought I would go to the OnPaint group and add to it.)

+6
c # resharper
source share
5 answers

The warning is true. Consider the following:

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

Here, the code modifies the formal parameter x, and then never uses the modified x. This does not change "this.X"

You did the same with the delegate. You change the formal parameter and then never use the result; the original "OnPaint" has not changed, just like the "X" in my example has not changed.

Remember that just because a delegate is a reference type does not mean that you pass a variable reference when you pass an instance. You are passing a link to the instance, not a link to the storage location of that instance.

+8
source share

Does it even work? I do not expect MyPaint to ever be called. That would be the key.

It seems to me that onPaint += MyPaint; will have no effect outside this method. onPaint is a parameter (local variable), and changes are lost when the method exits. That is why you get a warning.

To find out why you would need something like the ref parameter, but you cannot call it an event (this.Onpaint):

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

Delegates are immutable, so the union creates a copy. When you call:

 private void SomeOtherMethod(Action<PaintEventArgs> onPaint) 

In fact, you are creating a modified copy of the original Action<PaintEventArgs> .

Speaking of this, I personally will not try to work this way, unless there are good reasons for this.

Personally, I would think of creating an interface that provides an OnPaint event and passes the interface to this method. Then you can sign up for the event. This will have the same effect that you are trying to achieve, but it will be much more understandable.

In this case, I just want your other class to subscribe to the Paint event in the control directly.

+5
source share

Delegates are immutable. You cannot change them. In this regard, they are a bit like strings. Imagine your method:

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

Again, this will be a meaningless method. The original line would not change - you would just change the value of the local variable (parameter) to refer to another line. The same thing happens in the matter of delegation.

Either you need to pass the variable by reference, or you need to change the whole design.

For more on how delegate pooling works, see my article on delegates and events .

+5
source share

After some experimentation, I think the reason is that when you do += in Action , you are not changing the initial value, but rather a local variable. For example:

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

... just gives a click.

Thus, the MyPaint method in your example does not change, but only the onPaint variable. Since you are not doing anything with this variable after += , first of all you do not need to do += .

Edit

Porges points out that since OnClick is a method (not a delegate), this example is not entirely accurate. It's better here:

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

Output: test

+2
source share

All Articles