Is there some sort of annotation I can add to an extension method to let the anazyzer know that an object has been checked for null?

Hello all,

    I am hoping to get rid of a bunch of (Possible 'System.NullReferenceException') items that show up in my code, because it seems that Rider doesn't detect that I have already checked for null.

I have extension methods in which I am checking for null via `myCollection.IsNullOrZero()`

if (myCollection.IsNullOrZero())
{
Debug.Log("Something");
return;
}

for (int i = 0; i < myCollection.Length; i++)
{ // ^ Gives Possible 'System.NullReferenceException'
   myCollection[i].DoSomething();
}

Is there some sort of way to let the analyzer know that the .IsNullOrZero() extension method is doing a null check, and that this particular item will not be null and there is no need report it?

0
5 comments

Hello,

Would you mind sharing complete code snippet I could use to reproduce your scenario? (or uploading the whole solution. You can upload it to JetBrains Uploads service and let me know the Upload ID)

It is not clear what the myCollection is and what the IsNullOrZero method does.

Thank you in advance!

0

Sorry, I should have included that. In this case, it is quite simple. I have a static class with several different methods. Here is the actual code I am referring to that prompted my original post.

List<DataObject> dataObjects = parameters[0] switch {
  DataObject dataObject           => new List<DataObject> {dataObject},
  List<DataObject> dataObjectList => dataObjectList,
_                               => default
};

if (dataObjects.IsNullOrZero())
{
    Log("DataObjects are null or zero", Level.Error);
    return;
}

for (int i = 0; i < dataObjects.Count; i++)
{
    if (!DataObjectSceneChecks(dataObjects, i, activeScene)) return;
}

Then, this is the extension method being called, which is located in a separate static class.


// --| Extension Method in static class
public static bool IsNullOrZero(this IList input)
{
  return input == null || input.Count == 0;
}

 

As you can see below, it doesn't seem to count as a 'null check', unless there is something I am missing?

Of course, if I just inline that IsNullOrZero() method, the 'Possible Null' message goes away (seen below), so there must be something about it.

I was hoping that I could annotate the IsNullOrZero method as something is [IsNullCheck] so the analyzer knows that I checked for this. I am guessing it does not exists, but figured it was worth an ask.

0

Hello,

Thank you for the details shared. 

The solution depends on whether you are using the C# Nullable Reference Types feature or JetBrains annotations. Please take a look at the following code snippets:

using System.Collections;
using System;

namespace NullableReferenceTypes
{
  #nullable enable
  using System.Diagnostics.CodeAnalysis;

  public class C
  {
    public void Usage(IList? list)
    {
      if (list.IsNullOrZero())
      {
        return;
      }

      for (var index = 0; index < list.Count; index++)
      {
        Console.WriteLine(list[index]);
      }
    }
  }

  public static class MyExtensions
  {
    public static bool IsNullOrZero([NotNullWhen(false)] this IList? input)
    {
      return input == null || input.Count == 0;
    }
  }
  #nullable disable
}

namespace WithJetBrainsAnnotations
{
  #nullable disable

  using JetBrains.Annotations;

  public class C
  {
    public void Usage([CanBeNull] IList list)
    {
      if (list.IsNullOrZero())
      {
        return;
      }

      for (var index = 0; index < list.Count; index++)
      {
        Console.WriteLine(list[index]);
      }
    }
  }

  public static class MyExtensions
  {
    [ContractAnnotation("null => true")]
    public static bool IsNullOrZero([CanBeNull] this IList input)
    {
      return input == null || input.Count == 0;
    }
  }
}

If there is anything else I can assist you with, please let me know.

Have a nice day!

1

This is great, thank you much for taking the time to help with this. This is just what I was hoping for. 99% of my C# programming is within the context of Unity, as such, there is never much talk of things like the nullability features, but I am guessing it must be disabled, as the second example seems to have done the trick.

0
Hello,

Thank you for keeping me posted! I am glad to hear that I was able to help.
If there are no other questions, then I am going to proceed with archiving this ticket.
Should you have any other questions or difficulties in the future, do not hesitate to contact support.

Have a nice day!
0

Please sign in to leave a comment.