如何在特定类的NullReferenceException上自动抛出自定义异常?

时间:2016-08-31 06:30:39

标签: c# .net

public class Dog 
{

    public string Name { get; set;}
}

然后在这种情况下,null被传递给FeedDog()

public void FeedDog(Dog dog)
{

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

如何执行此操作以便在不执行此操作的情况下抛出DogDoesNotExistException

public void FeedDog(Dog dog)
{

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

所以当你这样做时

public void FeedDog(Dog dog)
{

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

5 个答案:

答案 0 :(得分:2)

一种方法是捕获global error handler中的错误并从那里重新抛出,但这会影响每个类。

因此,您应该考虑使用AOP(参见what-is-aspect-oriented-programming)。

例如,如果您使用依赖注入,则可以使用拦截器

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

这个附加类将包装每个方法调用。重新抛出的try catch逻辑可以在那里站点。如果你确实想要这样做,我会建议将原始异常添加为内部异常。

如果您正在使用MVC,您还可以使用过滤器属性。

尽管如此,我会小心捕获这样的Null Ref错误,因为它们非常通用。

答案 1 :(得分:1)

public void FeedDog(Dog dog)
{

    try
    {
        Console.WriteLine("Feeding " + dog.Name); 
    }
    catch(NullReferenceException e)
    {
        throw new DogDoesnotExistException();
    }
}

答案 2 :(得分:1)

我不明白为什么你需要这样做,但是一种方法是使用包装对象的结构并将结构作为方法参数传递。

有一个例子:

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);
    }
}

用法:

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

隐式转换运算符允许您以相同的方式调用方法:

Dog dog = GetDog();

FeedDog(dog);

答案 3 :(得分:0)

DogDoesNotExistException传递给null时,您不应抛出FeedDog。检查null并抛出ArgumentNullException以表示FeedDog被错误地使用,或者如果在dog实例的上下文中使用该方法,则根本不检查它无论如何应该在身边。

如果你实际上没有狗,你就不会去你的柜子里拿出狗食并把它放在碗里。如果你已经知道你有一只狗,你只能得到并准备食物。

因此,如果您没有狗(FeedDogdog),则不会致电null。相反,你要确保狗首先存在:

var dog = GetDogFromSomewhere();

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

FeedDog(dog);

答案 4 :(得分:0)

另一种方法是避免在任何地方使用null,而是创建一个名为&#39; EmptyDog&#39;的派生类。在任何属性访问中抛出异常。

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

在Dog类中为此创建一个单例:

 public static readonly Dog EmptyDog = new EmptyDog();

现在你可以在任何地方使用这个EmptyDog而不是null Dog,或者你可以使用一行来防止空值,然后依赖属性覆盖来引发异常,如果有人实际上试图调用该狗的名字

e.g。

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

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

请参阅null object pattern