2

So I've got a little method that looks like:

public static bool AnyNull(params object?[] args)
{
    if (args.Any(a => IsNull(a)))
    {
        return true;
    }
    return false;
}

private static bool IsNull([NotNullWhen(false)] object? obj) => obj is null;

e.g.

var maybeNullObj1 = source1.GetValue();
var maybeNullObj2 = source2.GetValue();
...etc

if(AnyNull(maybeNullObj1, maybeNullObj2, ...)){
    return;
}

// Do something without nullable warnings

The goal here is to be able to just throw a bunch of objects in the function and assert that they aren't null, to avoid these big chains of if (x == null) return;. However I'd like this to get rid of nullability warnings in the calling method. Unfortunately the above does not work, despite the attempt at NotNullWhen. Does anyone have any idea how you could do this?

7
  • 2
    You mean you want the caller to know that each of the individual params values is not null? (you should provide a code sample to highlight this) Yeah, I don't see how that could work. The best way to avoid lots of not-null test, is to keep pushing knowledge of not-null constraints up the call stack. Commented Sep 11 at 4:50
  • I'm pretty sure that this is not possible for the whole array. The best you can do is to create an extension method like IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> self) that filters all the null-items or an extension method like IEnumerable<T> ThrowOnNullItem<T>(this IEnumerable<T?> self) that throws an ArgumentNullException if an null item is found. But in that case your variable should be declared as IEnumerable<T> instead of allowing the caller to pass an null item just to punish him with an exception. Commented Sep 11 at 5:04
  • 2
    very minor - like "all the minors", but: that's not an extension method Commented Sep 11 at 5:52
  • @MarcGravell Yes I know. But the extension method is able to convert an IEnumerable<T?> to an IEnumerable<T> - and that is an extension method. But that filters the elements away - that does not ensure that all the elements are not null. That's why this is only a comment and not an solution. Commented Sep 11 at 6:15
  • @SebastianSchumann I was actually directing that at OP, i.e. the title "AnyNull extension method" Commented Sep 11 at 10:05

1 Answer 1

7

The [NotNullWhen(...)], if used on AnyNull, would apply to the array parameter args, not the individual elements, so no: you can't change that. However, in reality there are likely to be a short number of arguments, so: overloading rather than params might fix this for you and avoid unnecessary array allocations (also: there's no reason to use LINQ here - that too is just overhead):

public static bool AnyNull(
    [NotNullWhen(false)] object? arg0)
    => arg0 is null;
public static bool AnyNull(
    [NotNullWhen(false)] object? arg0,
    [NotNullWhen(false)] object? arg1)
    => arg0 is null | arg1 is null;
public static bool AnyNull(
    [NotNullWhen(false)] object? arg0,
    [NotNullWhen(false)] object? arg1,
    [NotNullWhen(false)] object? arg2)
    => arg0 is null | arg1 is null | arg2 is null;
public static bool AnyNull(
    [NotNullWhen(false)] object? arg0,
    [NotNullWhen(false)] object? arg1,
    [NotNullWhen(false)] object? arg2,
    [NotNullWhen(false)] object? arg3)
    => arg0 is null | arg1 is null | arg2 is null | arg3 is null;
public static bool AnyNull(
    [NotNullWhen(false)] object? arg0,
    [NotNullWhen(false)] object? arg1,
    [NotNullWhen(false)] object? arg2,
    [NotNullWhen(false)] object? arg3,
    [NotNullWhen(false)] object? arg4)
    => arg0 is null | arg1 is null | arg2 is null | arg3 is null | arg4 is null;
Sign up to request clarification or add additional context in comments.

1 Comment

I think this might be the best solution for this, thanks Marc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.