1

How can I make sure that a certain instance of a class will never be null? Someone told me to use Debug.Assert() but by doing so, I would only ensure that the code works in debug mode, whereas I want to ensure the is-never-null condition in release as well.

For example, in the past I wrote code like:

public string MyString
{
get
{
    if(instance1.property1.Equals("bla"))
    {
        return bla; 
    }
}
}

But this throws an exception if instance1 is null. I would like to avoid making such mistakes and generating such exceptions in the future.

Thanks,


please see a specific example below that illustrates the problem:

I have a method that authenticates users based on responses from a server. The method is this:

        /// <summary>
    /// attempts authentication for current user
    /// </summary>
    /// <returns></returns>
    public AuthResult CheckUser()
    {
        WebRequest request = WebRequest.Create(GetServerURI);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";

        string postdata = "data=" + HttpUtility.UrlEncode(SerializeAuth());
        byte[] arr = Utils.AppDefaultEncoding.GetBytes(postdata);
        request.ContentLength = arr.Length;
        request.Timeout = Convert.ToInt32(TimeUtils.GetMiliseconds(10, TimeUtils.TimeSelect.Seconds));

        Stream strToWrite = request.GetRequestStream();
        strToWrite.Write(arr, 0, arr.Length);

        WebResponse response = request.GetResponse();
        using (Stream dataFromResponse = response.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(dataFromResponse))
            {
                string readObj = reader.ReadToEnd();
                return DeserializeAuth(readObj);
            }
        }
    }

to call this method, i use

_authenticationResult = authObj.CheckUser();

I also have this property, among others

        public ResultType AuthResult
    {
        get
        {
            if (_authenticationResult.auth == "1")
                return ResultType.Success;
            if (_authenticationResult.auth == "0")
                return ResultType.FailAccountExpired;
            if (_authenticationResult.auth == "-1")
                return ResultType.FailWrongUsernameOrPassword;
            if (_authenticationResult.auth == "-2")
                return ResultType.Banned;


            return ResultType.NoAuthDone;
        }
    }

public enum ResultType { Success, FailWrongUsernameOrPassword, FailAccountExpired, NoAuthDone, Banned }

what happened was that _authenticationResult was null once, and the property AuthResult threw a nullref at attempting "null.auth". How can I ensure (perhaps inside the CheckUser() method) that it never returns null.

When i debugged the app it never happened. But in production, when the server timed out sometimes the method returned null.

Thanks,

Amc_rtty
  • 3,662
  • 11
  • 48
  • 73
  • 2
    That code wouldn't actually work - you need to always return something from `get` AFAIK...what should happen in release mode when `instance1` is `null` ? – Yahia Nov 08 '11 at 14:31
  • thanks - this is just some pseudocode. Usually I write these properties with a second return as well, after the if block. In release mode if the instance1 is null then I get a nullref exception. I believe what I do is bad coding practice and maybe there's something more elegant to do. – Amc_rtty Nov 08 '11 at 14:35
  • @Yahia: You are right that the code doesn't work, but it is because there is no return when `property1` is not equal to "bla". If `instance1` or `property1` are `null` and exception is thrown. – unholysampler Nov 08 '11 at 14:35
  • 1
    @unholysampler yes... my question was not what happens when `instance1` is `null` for example but what *should* happen it such a case ? a specific exception ? – Yahia Nov 08 '11 at 14:39
  • 1
    What is the different between debug and release? Normally, `assert` is on during the debug and is off in the release version. – wannik Nov 08 '11 at 14:40
  • I now understand your question, Yahia, sorry for the confusion - what should happen is, if the object SOMEHOW, by some reason gets null, its properties should never be called, thus generating an exception. My intention is to either avoid getting an exception, or handling it elegantly – Amc_rtty Nov 08 '11 at 14:41
  • 1
    Looking at the code example you posted, I think the elegant way to do this is to refactor your class (perhaps by breaking it into two classes, or other approaches we could discuss) so that there's absolutely no way for your caller to call AuthResult prior to the line _authenticationResult = authObj.CheckUser(); being executed – Corey Kosak Nov 08 '11 at 15:25

6 Answers6

6

I think you need to understand how instance1, and subsequently property1 are going to be instantiated, and only instantiate them in such a way that they cannot be null. This is generally done by checking arguments at construction, e.g.:

public instance1(string property1)
{
    if (property1 == null) throw new ArgumentNullException("property1");

    this.property1 = property1;
}

If you create your types in such a way that they cannot exist in an invalid state, you ensure that your dependent code won't fall over on null values.

Otherwise, we'd need to see a fuller example of what you are doing to give you more concrete advice.

The other thing to consider, is what state your class can exist in which is a required state of operation, vs. an optional state of operation. That being, what members are required for your class to operate, and you should endeavour to design your classes such that they always have the required state, e.g.:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }
}

In my example type, I'm requiring that my Forename and Surname value have a non-null value. This is enforced through my constructor... my Person type can never be instantiated with null values (although, perhaps empty values are just as bad, so checking IsNullOrWhiteSpace and throwing an appropriate ArgumentException is the route, but lets keep it simple).

If I were to introduce an optional field, I would allow it to mutate the state of my Person instance, e.g., give it a setter:

public class Person
{
  public Person(string forename, string surname)
  {
    if (forename == null) throw new ArgumentNullException("forename");
    if (surname == null) throw new ArgumentNullException("surname");

    Forename = forename;
    Surname = surname;
  }

  public string Forename { get; private set; }
  public string Surname { get; private set; }

  public string Initial { get; set; }
}

My Person type still enforces the required fields for operation, but introduces an optional field. I then need to take this into consideration when performing an operation which uses these members:

public override ToString()
{
  return Forename + (Initial == null ? String.Empty : " " + Initial) + " " + Surname;
}

(Although that is not the greatest example of a ToString).

Matthew Abbott
  • 60,571
  • 9
  • 104
  • 129
  • this is very good advice, I will remember this for the future. I have also updated the initial post with a specific example as per your request. thank you – Amc_rtty Nov 08 '11 at 15:16
  • I feel checking to see if a string is null is sort of silly. If you intialize all strings to be an empty string, you don't have to worry about a null value, and there is always IsNullOrEmpty. – Security Hound Nov 08 '11 at 15:30
  • @Ramhound This can sometimes be the case, but there *could* be a situation where there should be a difference between something being `null` vs. `Empty` vs. having a value. It would depend on how he expects the consumers of his types to behave with those different values. – Matthew Abbott Nov 08 '11 at 15:31
2

You can use:

if ( instance1 != null && instance1.property1.Equals("bla")){
   // Your code 
 } 
Upul Bandara
  • 5,973
  • 4
  • 37
  • 60
  • Thank you for your response, I know that, I do it all the time. I was looking for something like a good coding practice, some answer along the lines of unit tests or anything similar. – Amc_rtty Nov 08 '11 at 14:32
  • Your solution is helpful - but still not what I was looking for. But I was ambiguous in my initial post - verifying if the object is null, is treating the effect, not the cause - I need to treat the cause itself, to never allow the object to be null in the first place. – Amc_rtty Nov 08 '11 at 14:45
  • Then it is your responsibility to initialize instance1 correctly. – Upul Bandara Nov 08 '11 at 15:03
  • @Andrei Cristof - Checking to see if an object is null before you attempt to use a reference to it is not "treating the effect" as you put it. You even recgonize what your doing is not the "correct" way to do it. – Security Hound Nov 08 '11 at 15:32
1

Personally, I would use the ?? operator (assuming property1 is a string)

public string MyString
{
    get { instance1.property1 ?? "Default value"; }
}
Connell
  • 13,925
  • 11
  • 59
  • 92
1

People generally handle this situation in one of three ways. The worst way (in my opinion) is to be paranoid about every reference you look at, always testing it against null, and then doing ""something"" if you do encounter a null. The problem with such an approach is that you're often deep in some call tree, and so the "something" you do (like return a """reasonable""" default value) not only is likely to be a layering violation, but also is likely to paper over a problem rather than cause it to be confronted. In these cases it's actually probably better to let a NulLReferenceException be thrown rather than make some half-assed attempt to continue.

The saner thing to do is establish a coding convention where your references are never null, except in a few cases where it is obvious from context that they can be null. Additionally, and wherever possible, one can make one's classes immutable or mostly-immutable so that all the invariants can be done in the constructor and the rest of the code can get on with its life. For example, I might write:

public class Person {
  private readonly string firstName;
  private readonly string lastName;
  private readonly Nubbin optionalNubbin;
}

...where it is clear from the name that optionalNubbin might be null.

The final and most radical approach is to write code that will not admit a null. You could invent the dual of Nullable<T>, namely:

public struct NonNullable<T> {
  ...
}

The implementation could work in a few different ways (either by using an explicit Value property, or perhaps using operator overloading) but in any case the job of NonNullable is to never let someone set it to null.

Corey Kosak
  • 2,615
  • 17
  • 13
0

Since instance1.property1 should never be null, see if there's a way to initialize it properly, then thrown an ArgumentNullException if someone tries to set it to null.

Example:

public string Property1
{
    set 
    {
      if(value == null)
      {
        throw new ArgumentNullException();
      } 
      instance1.property1 = value;
    }
}
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
0

you can do something like below.

public string MyString
{
    get
    {
        if(instance!=null && instance1.property1.Equals("bla"))
        {
            return "bla"; 
        }
        else 
        {
            return String.Empty; 
        }
    }
}

This will basically check first whether instance is null or not.

NullUserException
  • 83,810
  • 28
  • 209
  • 234
VRK
  • 400
  • 2
  • 5