Null-treat pessimistic mode: how make ReSharper be satisfied when using predicates

Answered

Hi,

I get used to pessimistic null checking. It is a very effective tool, but unfortunately sometimes annoying. I'm trying to find the simplest solution to make ReSharper silent in some cases like below.

So, let's consider a method

public static T FirstOrDefault<T>([NotNull] this IReadOnlyList<T> list, [NotNull]Func<T,bool> func)
{
  if (list.Count == 0)
     return default;

  return Enumerable.FirstOrDefault(list,func);
}

Now a usage:

[NotNull]
[ItemNotNull]
private readonly List<SomeClass> _someList = new List<SomeClass>();

.....

var firstOrDefault = _someList.FirstOrDefault(x => x.MyProperty == value);

 

Resharper warns me that x.MyProperty may cause null-reference exception. But I know that my list does not contain null items, so, in fact, this warning can be removed. To mark each usage with a supression is not a solution. The best solution I came up is to use assertions. Currently, I use my AssertNoNull extension method:

/// <summary>
/// Returns a value of nullable-type, checking it for !=null. If the object is null, then throws the exception <see cref="ArgumentNullException"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="aObject"></param>
/// <returns></returns>
[ContractAnnotation("null=>halt")]
[AssertionMethod]
[NotNull]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T AssertNoNull<T>([AssertionCondition(AssertionConditionType.IS_NOT_NULL)] this T aObject)
{
#if DEBUG
Debug.Assert(aObject!=null, "aObject==null");
#endif
return aObject;
}

So, my code looks this way:

var firstOrDefault = _someList.FirstOrDefault(x => x.AssertNoNull().MyProperty == value);

Now I have no warning, but code looks a bit awkward and this assertion - mindless

What's more interesting, if I use standard Linq methods (in my example this is Enumerable.FirstOrDefault), Resharper understands them and does not warn me. So, in theory it is possible to teach ReSharper  to "recognize" my methods as well

Are there any solutions? Please, advise

 

 

3 comments
Comment actions Permalink

Try adding [InstantHandle] to your func parameter.

public static T FirstOrDefault<T>([NotNull] this IReadOnlyList<T> list, [NotNull, InstantHandle] Func<T, bool> func)

However, I'd be surprised if that method gives you any noticeable performance benefit over the standard Linq method, unless most of the lists you pass to it are empty. You're saving an allocation for the enumerator in the degenerate case, but adding the overhead of an extra method call in the normal case. I'd suggest benchmarking your code with both options to see what difference it makes.

0
Comment actions Permalink

[InstantHandle] did not help

FirstOrDefault is just an example. Do not pay attention to what it does. I used this method for experiments: as soon as remove my method from code, a default Enumerable.FirstOrDefault method is used instead and ReShraper does not complain about possible null-reference anymore. Thus, I see it recognizes standard enumerable methods somehow and ignores them

0
Comment actions Permalink

There is no way to annotate the FirstOrDefault method.

0

Please sign in to leave a comment.