Home > Enterprise >  "Expression is always true" warning for reference type?
"Expression is always true" warning for reference type?

Time:01-10

I have the following piece of code with warning Expression is always true:

public class MyClass
{
    private readonly IHubContext<NotificationHub> _hubContext;

    public MyClass(
        IHubContext<NotificationHub> hubContext)
    {
        _logHandler = logHandler;
        _hubContext = hubContext;
    }
            
    foreach (string group in groups)        
    {
        IClientProxy connection = _hubContext.Clients.User(group);
        if (connection != null) // Expression is always true
        {
        }
    }
}

I know that Resharper is very smart, however I cannot understand why it says Expression is always true as IClientProxy is reference type. IClientProxy resides in Microsoft.AspNetCore.SignalR namespace. Do you know why Resharper says Expression is always true?

This is how User is declared in public interface IHubClients<T>:

public interface IHubClients<T> 
{
    /// <summary>
    /// Gets a <typeparamref name="T" /> that can be used to invoke 
    /// methods on all connections associated with the specified user.
    /// </summary>
    /// <param name="userId">The user ID.</param>
    /// <returns>A client caller.</returns>
    T User(string userId);
}

UPDATE:

If I add ? sign:

IClientProxy? connection = _hubContext.Clients.User(group);

Then I will get the following warning:

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

UPDATE 1

Even if I use var:

var IClientProxy? connection = _hubContext.Clients.User(group);
if (connection != null)

then warning is arised Expression is always true:

enter image description here

CodePudding user response:

Firstly, we should note that the warning is from Resharper, and not the actual compiler. If you disable Resharper, that particular warning will go away.

That said, it is a valid warning. To understand why, consider the following interface definition:

public interface IDemo<T>
{
    public T Func();
}

That definition states that Func() will not return null. If it could return null, it would be defined using T? thus: public T? Func();

A simple implementation of that interface could look like this:

public sealed class Demo<T>: IDemo<T> where T: new()
{
    public T Func()
    {
        return new T();
    }
}

This compiles OK. However, if you change the implementation of Func() to:

public T Func()
{
    return null;
}

you will get a real (not Resharper) compile error:

error CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.
warning CS8603: Possible null reference return.

Now consider this code (where I chose an arbitrary type with a default constructor for illustration, in this case Random):

IDemo<Random> test = new Demo<Random>();

if (test.Func() != null)
{
    Console.WriteLine("Not null");
}

This provokes the Resharper warning that you're seeing, the reason being that IDemo<Random>.Func() has been specified to return non-null, as explained above.

The method you are using is declared as public T IHubClients<T>.Client(String) - i.e. it returns T and not T? - which means it can never (or should never) be null.

Thus when you check it for null, Resharper is warning you because you should not need to do that.

  • Related