4

I have code like this (simplified):

long counter = 0L;

var t = Task.Run(async () =>
{
    Interlocked.Increment(ref counter); // Resharper: "Access to modified closure"
    await Task.Delay(500);               // some work
});
// ...
t.Wait();
// ...
Interlocked.Decrement(ref counter);

counter variable is used to control total number of something in progress.

In the lambda (as well as outside it) the variable is only referenced with ref. How does the compiler process such captures? Is it guarantied that all delegates (if many) will get the same reference to counter, not to "individual" copied variables? I tested it and it works as expected, but I want to be sure.

  1. Is it safe to use explicit ref counter for interlocked change and read?

  2. Why does Resharper gives this wacky suggestion to wrap the variable in one-element array? Like this: long[] counter = {0L}, Interlocked.Increment(ref counter[0]). Can you provide a use-case when it helps or fixes something?

P.S. The question was induced by another my question.

NOTE: I am aware what closure is and how it works in common cases. Before marking the question as duplicate read concrete questions 1 and 2. I did not find answers to these questions in multiple "loop-closure" questions in Internet and SO.

greatvovan
  • 2,439
  • 23
  • 43
  • @Servy I disagree with the duplicate. This question is specifically looking for information about how a parameter declared `ref` inside a lambada could behave incorrectly. Basically he wants to know the reason behind ReSharper's suggestion of changing it to a single element array. The linked duplicate does not address that in any of the answers I read through. – Scott Chamberlain Jan 10 '18 at 19:39
  • @ScottChamberlain The question is asking how it's possible to access a closed over variable by reference, and if it would work. The duplicate answers that exact question. It explains why you're able to access a variable by reference, how it's implemented, and why that works. The fact that this question *wants* it to behave the way it actually does, and the other question *doesn't*, doesn't affect the explanation of how it actually behaves. – Servy Jan 10 '18 at 19:40
  • If you're aware of how closures work, and that closures close over variables, not values, then why are you asking of a closure will have a copy of the variable's value, rather than the variable itself, when all of the questions on the topic specifically say (and explain why) a closure doesn't copy the variable's value? – Servy Jan 10 '18 at 19:44
  • @Servy I don't read it that way, I read it as "What is the use case of using `ref` on a closed over variable that resharper is concerned with that it is recommending I change it in to a single element array", I guess qustion 1 is a duplicate, but question 2 is not and I think it is the main point of the overall question. greatvovan I recommend you remove question 1 and reword your question to focus more on question 2. – Scott Chamberlain Jan 10 '18 at 19:44
  • @ScottChamberlain The question is asking how closures are implemented, if they result in a copy of the variable being made, and if, as a result, using `ref` on a variable in a closure will result in a reference to a copy of the variable made, and wonders how resharpers suggestion fixes that perceived problem. – Servy Jan 10 '18 at 19:47
  • Here is similar question: https://stackoverflow.com/q/6467129/5311735 – Evk Jan 10 '18 at 19:50
  • @Servy I am trying to "expand" this code into auto-generated closure (the way as the compiler does). I don't completely understand how `ref closure.counter` will work. Moreover you completely ignored my second question. I want to know why does it suggest it and when it is applicable. – greatvovan Jan 10 '18 at 19:51
  • @Servy as I mentioned, Resharper's suggestion does not seem to fix or change anything. That's why I made focus on it. If I am wrong I want to know where. If I am right, I want to know where this suggestion works. Update: I mean not only `ref` use-case here, but general usage. – greatvovan Jan 10 '18 at 19:53
  • @greatvovan Do you understand what you want your code to do? Do you understand what the resharper warning is telling you about your code? I gave you a link that goes over it in more detail, if you want to read more on it. If you know what you want to do, and you know what the resharper warning is telling you about your code, then you'll understand what you want to do as a result of the warning. – Servy Jan 10 '18 at 19:54
  • @Servy with the links from Evk and you that where provided about the resharper warning I now agree that this is a duplicate. – Scott Chamberlain Jan 10 '18 at 19:56
  • @Servy your second link is useful, thanks. – greatvovan Jan 10 '18 at 20:00
  • @greatvovan In the future if you have a question about something you should do a web search for that thing (in this case, the resharper warning you don't understand). Just asking an SO question about something without even looking at even the first google result is not very considerate. – Servy Jan 10 '18 at 20:01
  • To be honest even after reading all duplicates I still have no idea what's the point of "wrap to array" suggestion, which doesn't do anything useful and just hides potential isue under the carpet (not here, here there is no issue in the first place, but in general). – Evk Jan 10 '18 at 20:04
  • @Evk There is no point. That's exactly what the duplicates say. The behavior is exactly as desired right from the start. – Servy Jan 10 '18 at 20:16
  • @Servy I understand (even saying that here there is no issue in the first place), but somehow the idea of wrapping into array was implemented in Resharper and survived several releases, and I don't see why it ever can be useful (not in this case but ever at all). – Evk Jan 10 '18 at 20:23
  • @Evk It isn't ever useful. There is never a situation where you'd want to do this refactor, at least in the exact situation described. There are cases where it could be useful to wrap a value type into a single valued array (basically exactly the situations in which you'd want to box an object; you want to be able to treat a value type like a reference type) but that's not helping here as the closure is already wrapping the value type into a reference type object for you, so you don't need to do it again. – Servy Jan 10 '18 at 20:28
  • @Servy The second link is not in top Google results, and there is no good answers to the second question in top results (in my Google). Your third link IS in top, but it does not answer WHY Resharper suggests this. Only the second link makes insight on this matter. – greatvovan Jan 10 '18 at 20:33
  • @Servy I see you suffered too much from this question, sorry for this. But your recommendation is not applicable to me. I always do my own research before asking questions (first of all this is faster for me). Please do not transfer your own (or whom?) behavior models on unfamiliar people. Reaction like yours is counter-productive and may discourage people from asking questions. – greatvovan Jan 10 '18 at 20:35
  • @greatvovan Saying that you did your own research, when you didn't even find the top search result for the warning you wanted to know more about, doesn't mean a whole lot. If you did your research, you'd have found it; that you didn't find it mean you *didn't* do adequate research. – Servy Jan 10 '18 at 20:39
  • @Servy I see you don't read carefully again. I did find the third link, but it was unsatisfactory for me. – greatvovan Jan 10 '18 at 20:44
  • @Evk I can suppose it may be related to how Resharper works internally. Wrapping a variable into array makes super-obvious that the new variable (which is array) is not modified inside closure (but array's content may be modified, which is OK). Probably it's a workaround they invented to hide the warning. I agree it looks weird since it spoils readability too much. – greatvovan Jan 10 '18 at 20:52

0 Answers0