Can I handle "not initialized" warnings with Jetbrains Annotations?

I wrote a method that operates similar to the TryParse() methods of int or DateTime. Difference is: the out parameter is a ref parameter, because I don't want to touch the result variable if the parser fails.The pseudo code looks like this:public bool TryGetValue(InputType input, ref string result){   if (can parse input)   {      result = value of input;      return true;   }   return false;}Now, when I use it like this:string foo;if (TryGetValue(input, ref foo)){   use foo for something}then I get a warning that foo might not be initialized. Well, of course, if TryGetValue returns false, it won't be initialized. But if it returns true, everything is okay. That's the purpose of the return value.I could simply initialize foo with null, but I am curious: Can I tell R# somehow that foo is initialized when TryGetValue returns true? I tried[ContractAnnotation("=>true,notnull")]but it didn't help.I am using R# Ultimate 9.1.1Rolf Borchmann
2 comments
Comment actions Permalink

Hi Rolf. Yes, and no. :)

Firstly, the "not initialized" warning is actually a compiler warning, and can't be worked around by ReSharper. Given this code:

public void Thing()
{
  string doodad; // Uninitialised
  InputType input = new InputType();

  if (TryGetValue(input, ref doodad))  // Compiler complains!
    Console.WriteLine(doodad.Length);
  else
    Console.WriteLine(doodad.Length);  // (1)
}


When I try to build this, the compiler complains when trying to pass through "ref doodad". I have to initialise the variable first. Then the compiler is happy. So, the short answer here is no, you can't tell ReSharper that everything's ok, because ReSharper is only reporting what the compiler is unable to compile.

However, the ContractAnnotation can help with this construct. You can use something like:

[ContractAnnotation("=> false, result:null; => true, result:notnull")]
public bool TryGetValue(InputType input, ref string result)
{
  if (input != null)
  {
    result = "all good";
    return true;
  }

  return false;
}


This annotation does not look at input values, but only output values (so there is nothing on the left hand side of the "=>" fat arrow. What it says is that if the method returns false, result will be null. If it returns true, result will be not null.

And that means ReSharper can use that in the inspections in the original method - now ReSharper will highlight the usage of "doodad.Length" at (1) above, as generating a possible NullReferenceException, because the contract tells it that when the method returns false, result is null.

0
Comment actions Permalink

"[ContractAnnotation("=> false, result:null; => true, result:notnull")]" is ok when you have "result" as "out" parameter because you have always assign some value to it. But in this case you have "ref result" and actually do not change the value of the result when cannot parse the string, so the first part of the contract is misleading and the better annotation is "[ContractAnnotation("=>true, result: notnull]"

0

Please sign in to leave a comment.