One of our team likes to write code like this (C#):

if (_someVar != null)
{
    _someVar = null;
}

Rather than simply:

_someVar = null;

I've never used the former as I always assumed it was unnecessary, especially in a language like .Net. Before I get into a debate with them I wanted to know if there is any benefit in doing that check? This person comes from a Java background, so I wondered if this was a habit they have kept from that.

  • 20
    No, there is no benefit to the check whatsoever. It simply results in slower code (unless the compiler/JIT just optimises it away). People just do odd things... – David Arno Aug 4 '17 at 14:50
  • 13
    The only way this style of coding matters is if the call to _someVar causes side effects, but if it does, you have bigger problems than useless code. – Robert Harvey Aug 4 '17 at 15:24
  • 2
    You don't want to set it to null if it is already null! You wouldn't empty an empty garbage can would you? – Barry Franklin Aug 4 '17 at 18:00
  • 7
    @BarryFranklin. At first glance, that seems a silly analogy. However, the answer to that analogy would still be "yes" if emptying is fast. If you are a garbage man who has 100 bins in a street to empty, the most efficient way is to just empty them into the garbage truck. Stopping to assess whether the bin is empty first would be slower. Likewise, a waiter clearing a table doesn't assess whether cutlery is dirty or not; he simply collects the whole lot up and dumps it into the dishwasher. When the emptying/cleaning process is efficient, checking if the action is needed is a time waster. – David Arno Aug 4 '17 at 20:49
  • 3
    This person comes from a Java background, so I wondered if this was a habit they have kept from that. Nop. We don't do that either. – Laiv Aug 4 '17 at 21:54
  1. If _someVar is a property instead of a variable,

    • and setting it has side-effects, that might be functionally different code.
    • and setting it is considerably more involved than reading it, testing, and taking your chance with branch-misprediction, it might be more efficient.
  2. If _someVar is in device-memory (in which case it should be volatile, and that does not apply to .Net), the point about properties with side-effects applies.

  3. If _someVar is in shared accessed memory, doing so avoids unsharing the containing cache-line, which would avoid cache-line-bouncing.
    If it is expected to already be null, there shouldn't even be too much branch-misprediction.

  4. If _someVar is in a rarely modified memory-page, doing so will avoid dirtying the page, preserving disk-bandwidth used for writing back modified pages, be it just to be prepared or to free a page.

You will probably never benefit from considering any of those scenarios at all.
If one does apply, there should be an explicit comment justifying it as it's just too rare.
Nearly always, it's just an obfuscation and pessimization, and should be caught in code-review.

  • 1
    As a variation to your first point, reading the property may involve arbitrary work while setting it is trivial, so adding this extra null check could arbitrarily change behavior and increase the amount of work too. While I suspect this is less common than the other way around, it's not that unusual, e.g. lazy loading. – Derek Elkins Aug 5 '17 at 0:26
  • If you have a property with a setter, and setting the property to a different value has side effects that should be avoided if the property is set to the old value, then you should probably put code into the setter, and not outside. An example would be a button with a color property, which might be set gazillion times to the exact same value. If the setter is responsible for redrawing the button when the color changes (expensive) then it should check whether the new color is the same as the current color, not the code outside. – gnasher729 Aug 5 '17 at 12:09
  • @gnasher729 Indubitably. But maybe the component is not under your control, and it wasn't expected that there are any spurious calls to set the property? You must consider that if it simply does not ever happen, checking for it to happen anyway is just a waste. Just to explain how such an unfortunate situation might develop and not be resolved in the obviously best manner. – Deduplicator Aug 5 '17 at 12:37

Doing this as a matter of course for all cases when a variable is being set to null seems silly as I am certain it has absolutely no purpose 99.9% of the time. After the code has executed, the state of the variable will be identical in both scenarios. There may be a sub-sub-nanosecond difference if you need to run this a billion times, since CPU reads are faster than writes (without any caching, branch prediction, or operation re-ordering at all, writes are twice as slow, but that doesn't mean they will end up twice as slow once you add all those mechanisms back in, also the increased size of the code base and working set may offset any gains). But there is no functional difference.

It is conceivable there could be some functional difference in rare, exception cases, e.g. if the variable is marked volatile. In this case, the null check will put up a read memory barrier and will skip setting up a write memory barrier if it is already null. I can't imagine any legitimate purpose but it is possible some brainiac figured out a very subtle difference in some low level behavior, e.g. the null check may prevent a redundant null set from interfering with the CPU's write queue, solving some obscure problem I've never heard of.

I am sort of spitballing here, but I thought you might be interested in this very narrow possibility. I sure as heck never check for null before setting it, nor does anyone I know, nor does any example in any Knowledge Base article I've ever read.

Another interesting reason that a commenter noted is that it may be helpful to be able to set a breakpoint that will only fire when the reference is released. If you follow the pattern and put a breakpoint on the assignment, it'll work that way.

My final thought is maybe it is a holdover from the days when we did reference counting when releasing objects. With GC of course all those patterns are out of date now.

Perhaps don't approach this as a debate but a learning opportunity. Ask them why they do it. I am really curious what they will say.

Trust the compiler.

If the null-check would make sense, let the compiler insert it. Compiler writers spend days figuring out such micro-optimizations.

Write readable code

_someVar = null has the pleasant property that it's immediately clear what the final state is. No matter the previous state, the final state is null.

It makes no sense. The timesaving would be negligible.

It wouldn't make sense even in the case that we were to assign an object, because the object would needd to be already instantiated in order to perform the comparison, so no object creation overhead would be saved.

if ( ! _someVar.equals(myObj))
{
    _someVar = myObj;
}

It would only make sense if there was something else besides the null assignment to do, because runnign doThis() has some cost or if some some reason you don't want to run it twice:

if (_someVar != null)
{
    _someVar = null;
    doThis();
}

I can see a legitimate, albeit rare, case for this:

As others have said, suppose _someVar is a property. It has been criticized that if the side effects make it expensive that you've got a worse problem but I don't think that's always the case.

Consider a function that keeps some sort of audit trail. Now writing is legitimately expensive (maybe very expensive--writing the audit log to disk) without it being a case of unreasonable side effects.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.