dinotom
dinotom

Reputation: 5162

object is always not null

This has always driven me crazy and I still cant get my head around it. In the code below, the if statement is flagged by the editor saying that the "expression is always true"

 public Task ConfigSendMailAsync(IdentityMessage message)
    {

        const string usertoken = "Sent";
        var mailMessage = new MailMessage();
        mailMessage.To.Add(new MailAddress(message.Destination));
        mailMessage.From = new MailAddress("[email protected]");
        mailMessage.Subject = message.Subject;
        mailMessage.Body = message.Body;


        var credentials = new NetworkCredential(
                   ConfigurationManager.AppSettings["mailAccount"],
                   ConfigurationManager.AppSettings["mailPassword"]
                   );

         var mailClient = new SmtpClient {Credentials = credentials};

        ***if (mailClient != null)***
        {
            mailClient.SendAsync(mailMessage, usertoken);
            return Task.FromResult(0);
        }

        else
        {
            //log error
            return Task.FromResult(-1);
        }
    }

How is it always true, what if the message that was passed was invalid, what if there was a failure creating the credentials, etc. etc. Certainly something COULD make that if statement true. I get that if anything failed prior, I'd get an exception. If I wanted to ensure the credential was valid, Id certainly test for that.

 if (credentials != null)
        {

        }

But guess what, apparently thats always true as well. How can that be, what if there was nothing stored in those app settings? Can someone explain how this actually works and how best to structure this code

Upvotes: 0

Views: 226

Answers (5)

Fabio Salvalai
Fabio Salvalai

Reputation: 2509

How is it always true, what if the message that was passed was invalid, what if there was a failure creating the credentials, etc. etc.

In that case, perhaps an exception would be thrown, and the if would never be reached. You can trust the compiler on this one.

Same for credentials: You give an example of invalid credentials. They would be invalid, sure, but not null.

The only way you could have your if to return false would be if you swallow an exception occuring in the constructor (which would be a terrible idea, and the compiler would detect it and not display that warning any longer)

for instance:

 try
 {
     var mailClient = new SmtpClient {Credentials = credentials};
 }
 catch(Exception)
 {
     // Evil: you swallow your exception, mailClient is null
     // The program continues and god drowns a kitten.
 }

 if (mailClient != null)
 {
     mailClient.SendAsync(mailMessage, usertoken);
     return Task.FromResult(0);
 }

Upvotes: 1

displayName
displayName

Reputation: 14369

The condition (mailClient != null) is only a reference check.

If the variable mailClient would be a dangling pointer, this condition would fail. As long as you have a valid space carved out in memory with mailClient pointing to that memory space, it is not null.

The conditional that you are concerned with would ask - Does the mailClient point to anything valid? And the CLR would find out - Yes, the value in the reference type variable called mailClient is valid. The conditional would then be true as it is not null.

When you do var xyz = new Something(); you reserve a piece of memory and the variable now points to that memory in the heap. Even if you have not populated the fields of that member, the address stored in xyz not null anymore and that is how your conditional is always true.


Opposed to that, let's say you have a statement Something xyz;. All this means that xyz can store the address of a Something type object. However, this variable does not point to any valid address in memory space yet and is just a dangling pointer. This will cause your conditional check of (xyz != null) to fail.

Upvotes: 0

John Wu
John Wu

Reputation: 52210

In the code that you have, mailClient is never null, because your code just instantiated it. If there were a problem with the instantiation, the line above would have failed.

 var mailClient = new SmtpClient {Credentials = credentials};  //This line would throw an error if SmtpClient could not be instantiated
 if (mailClient == null)
 {
    throw new Exception("This will never happen.");
 }

You would need the null check only if you are using some function or factory pattern to create the object instance, e.g.

 var mailClient = SmtpHelper.CreateClient(credentials);
 if (mailClient == null)
 {
     throw new Exception("SmtpHelper returned a null client!");
 }

Upvotes: 1

Nathan
Nathan

Reputation: 6531

mailClient is never null

You just new'd it up. Maybe the field/property is null, that's not what you're checking there. Maybe something went terribly wrong and an exception was thrown and mailClient was never assigned, but then you wouldn't have got to that check.

Also this is how you write asynchronous code. Also, it's not SQL, we don't comminicate whether an method worked by returning a weakly typed integer.

Upvotes: 0

Thomas Weller
Thomas Weller

Reputation: 59228

Creating the SmtpClient object does not check the credentials for validity. It will just store them in fields for later use. The constructor will create a new object and the object will not be null. Conclusion: the if statement is always true.

What will happen though: the SendAsync() method may throw a SmtpException if credentials don't work. You'd need to catch the exception.

Upvotes: 1

Related Questions