1
public class Dog 
{

    public string Name { get; set;}
}

Then in this scenario null is passed to FeedDog()

public void FeedDog(Dog dog)
{

    Console.WriteLine("Feeding "+dog.Name); // throws NullReferenceException
}

How can I do this so that it throws DogDoesNotExistException without doing this

public void FeedDog(Dog dog)
{

    if (dog == null)
        throw new DogDoesNotExistException(); // want to get rid of this
    Console.WriteLine("Feeding "+dog.Name);
}

So when you do this

public void FeedDog(Dog dog)
{

    Console.WriteLine("Feeding "+dog.Name); // throws DogDoesNotExistException
}
Tim
  • 28,212
  • 8
  • 63
  • 76
bman
  • 3,740
  • 9
  • 34
  • 40
  • 3
    `GetDog` should throw the exception. – Alessandro D'Andria Aug 31 '16 at 06:33
  • 2
    This is a bad design. Not every `NullReferenceException` should be transformed into `DogDoesNotExistException` in this class. This is very error prone. You need to be explicit. Do you really need to throw the exception ? If the reason is for the exception to bubble up and be handled on a different layer then OK, but why no just return a boolean using the TryXXX pattern ? – Zein Makki Aug 31 '16 at 06:33
  • right I will update my question – bman Aug 31 '16 at 06:35
  • 1
    You can't do this. You don't have this level of control. The exception is generated deep down in the guts of the CLR. For comparison, they're only just getting around to trying to help discover *which variable* is responsible for NREs, in a future version of C# – Damien_The_Unbeliever Aug 31 '16 at 06:46
  • @Damien_The_Unbeliever I can accept your answer if you answer below – bman Aug 31 '16 at 06:54
  • @bman What if you add additional property like `Value` or `Instance` with type `DogInternal` (or something like this) into `Dog` class and use it instead of `dog` like so `dog.Value.Name` so you can throw exception in that additional property. – feeeper Aug 31 '16 at 06:57

5 Answers5

2

One approach is to capture the error in the global error handler and re-throw from there but this would effect every class.

Therefore you should look at using AOP (see what-is-aspect-oriented-programming).

For example if you are using dependency injection you can use an interceptor

http://docs.autofac.org/en/latest/advanced/interceptors.html

This additional class will wrap each and every method call. The try catch logic with re-throw can site in there. If you do really want to do this I would advise the original exception being added as an inner exception.

If you are in using MVC you can also use filter attributes.

With all that said I would be careful of capturing Null Ref errors like this as they are very generic.

Community
  • 1
  • 1
John
  • 29,788
  • 18
  • 89
  • 130
  • right i didn't say that I was doing this on MVC for checking the models and now looking at the filter attributes . – bman Aug 31 '16 at 07:03
1
public void FeedDog(Dog dog)
{

    try
    {
        Console.WriteLine("Feeding " + dog.Name); 
    }
    catch(NullReferenceException e)
    {
        throw new DogDoesnotExistException();
    }
}
Tim
  • 28,212
  • 8
  • 63
  • 76
FakeisMe
  • 464
  • 3
  • 9
  • thanks I know this is the way to do it but just hoping there is a way to do this "automagically" like if this Class has a nullreference exception throw this type of exception – bman Aug 31 '16 at 06:44
  • 2
    @bman I advise you not to do what you're stating. This is pure evil ! – Zein Makki Aug 31 '16 at 06:47
  • This appears to be a bad idea as soon as you do more complex stuff in the `try` block which could also throw a NRE on a different object. – poke Aug 31 '16 at 06:59
1

I did not understand why you need to do that, but one way to accomplish is using a struct that wraps the object and the pass the struct as method argument.

There an example:

struct DogWrapper : IEquatable<DogWrapper>
{
    readonly Dog _value;

    public Dog Value
    {
        get
        {
            if (_value == null)
            {
                throw new DogDoesNotExistException();
            }

            return _value;
        }
    }

    public DogWrapper(Dog value)
    {
        _value = value;
    }

    // TODO 
    //public override int GetHashCode()
    //{
    //    return base.GetHashCode();
    //}

    //public override bool Equals(object obj)
    //{
    //    return base.Equals(obj);
    //}

    //public override string ToString()
    //{
    //    return base.ToString();
    //}

    public bool Equals(DogWrapper other)
    {
        throw new NotImplementedException();
    }

    public static implicit operator DogWrapper(Dog value)
    {
        return new DogWrapper(value);
    }
}

Usage:

public void FeedDog(DogWrapper dog)
{
    Console.WriteLine("Feeding "+dog.Name); // now throws DogDoesNotExistException
}

The implicit cast operator let you call the method the same way:

Dog dog = GetDog();

FeedDog(dog);
Alessandro D'Andria
  • 8,663
  • 2
  • 36
  • 32
  • This is an interesting answer but I could not wrap my head around it, (no pun intended). I will read more about this – bman Aug 31 '16 at 08:31
0

You should not throw a DogDoesNotExistException when passing null to FeedDog. Either check for null and throw a ArgumentNullException to signalize that the FeedDog is being used incorrectly, or don’t check it at all if the method is used in a context where a dog instance should be around anyway.

You wouldn’t go to your cabinet and get out dog food and put it in a bowl if you don’t actually have a dog. You would only get and prepare the food if you already know that you have a dog.

So you wouldn’t call FeedDog if you don’t have a dog (dog being null). Instead, you would make sure that the dog exists first:

var dog = GetDogFromSomewhere();

if (dog == null)
{
    throw new DogDoesNotExistException();
}

FeedDog(dog);
poke
  • 369,085
  • 72
  • 557
  • 602
0

Another approach would be to avoid using null everywhere and instead create a derived class called 'EmptyDog' that throws your exception on any property access.

public class EmptyDog : Dog
{
   public override Name {get { throw new DogDoesNotExistException(); } }
   ...
}

Create a singleton for this in the Dog class:

 public static readonly Dog EmptyDog = new EmptyDog();

Now you can either use this EmptyDog everywhere instead of a null Dog, or you can protect against nulls with one line and then rely on the property overrides to throw an exception if someone actually tries to call that Dog's Name.

e.g.

  public void SomeMethod (Dog dog)
  {
     dog = dog ?? Dog.EmptyDog;

     // access properties and get an exception if dog was null
  }

See null object pattern.

Ian Mercer
  • 38,490
  • 8
  • 97
  • 133