C# 如何在特定类的NullReferenceException上自动引发自定义异常?

C# 如何在特定类的NullReferenceException上自动引发自定义异常?,c#,.net,C#,.net,然后在这个场景中,null被传递给FeedDog() 我如何做才能使它在不这样做的情况下抛出dogdesnotexistexception public void FeedDog(Dog dog) { Console.WriteLine("Feeding "+dog.Name); // throws NullReferenceException } 所以当你这么做的时候 public void FeedDog(Dog dog) { if (dog == null)

然后在这个场景中,null被传递给FeedDog()

我如何做才能使它在不这样做的情况下抛出
dogdesnotexistexception

public void FeedDog(Dog dog)
{

    Console.WriteLine("Feeding "+dog.Name); // throws NullReferenceException
}
所以当你这么做的时候

public void FeedDog(Dog dog)
{

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

一种方法是捕获错误并从中重新抛出,但这会影响每个类

因此,您应该考虑使用AOP(请参阅)

例如,如果您正在使用依赖项注入,那么可以使用拦截器

这个附加类将包装每个方法调用。重试捕获逻辑和重新抛出can站点。如果您真的想这样做,我建议将原始异常添加为内部异常

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


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

一种方法是捕获错误并从中重新抛出,但这会影响每个类

因此,您应该考虑使用AOP(请参阅)

例如,如果您正在使用依赖项注入,那么可以使用拦截器

这个附加类将包装每个方法调用。重试捕获逻辑和重新抛出can站点。如果您真的想这样做,我建议将原始异常添加为内部异常

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


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

在将
null
传递给
FeedDog
时,不应抛出
dogdesnotexistexception
。检查
null
并抛出
ArgumentNullException
以表明
FeedDog
使用不正确,或者如果该方法用于无论如何都应该存在dog实例的上下文中,则根本不检查它

如果你没有养狗的话,你就不会去你的柜子里拿出狗粮放在碗里。如果你已经知道你有一只狗,你才会得到和准备食物

因此,如果你没有狗(
dog
being
null
),你就不会调用
FeedDog
)。相反,您应该首先确保狗存在:

public void FeedDog(Dog dog)
{

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

null
传递给
FeedDog
时,不应抛出
dogdesnotexistException
。检查
null
并抛出
ArgumentNullException
以表明
FeedDog
使用不正确,或者如果该方法用于无论如何都应该存在dog实例的上下文中,则根本不检查它

如果你没有养狗的话,你就不会去你的柜子里拿出狗粮放在碗里。如果你已经知道你有一只狗,你才会得到和准备食物

因此,如果你没有狗(
dog
being
null
),你就不会调用
FeedDog
)。相反,您应该首先确保狗存在:

public void FeedDog(Dog dog)
{

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

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

有一个例子:

var dog = GetDogFromSomewhere();

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

FeedDog(dog);
隐式强制转换运算符允许您以相同的方式调用该方法:

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

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

有一个例子:

var dog = GetDogFromSomewhere();

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

FeedDog(dog);
隐式强制转换运算符允许您以相同的方式调用该方法:

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

另一种方法是避免到处使用null,而是创建一个名为“EmptyDog”的派生类,该类在任何属性访问时抛出异常

Dog dog = GetDog();

FeedDog(dog);
在Dog类中为此创建一个单例:

public class EmptyDog : Dog
{
   public override Name {get { throw new DogDoesNotExistException(); } }
   ...
}
现在,您可以在任何地方使用这个EmptyDog而不是null Dog,或者您可以用一行防止null,然后在有人试图调用该Dog的名字时,依靠属性重写抛出异常

e、 g


请参阅。

另一种方法是避免到处使用null,而是创建一个名为“EmptyDog”的派生类,该类在任何属性访问时抛出异常

Dog dog = GetDog();

FeedDog(dog);
在Dog类中为此创建一个单例:

public class EmptyDog : Dog
{
   public override Name {get { throw new DogDoesNotExistException(); } }
   ...
}
现在,您可以在任何地方使用这个EmptyDog而不是null Dog,或者您可以用一行防止null,然后在有人试图调用该Dog的名字时,依靠属性重写抛出异常

e、 g


请参阅。

GetDog
应引发异常。这是一个糟糕的设计。在此类中,并非所有
NullReferenceException
都应转换为
DogDoesNotExistException
。这很容易出错。你需要直言不讳。您真的需要抛出异常吗?如果原因是异常冒泡并在不同的层上处理,那么OK,但为什么不使用TryXXX模式返回布尔值?好的,我将更新我的问题您不能这样做。你没有这种程度的控制。异常是在CLR的内部深处生成的。作为比较,他们只是想找出哪个变量是导致NREs的原因,在未来版本的C#@Damien_中,如果你回答下面的问题,我可以接受你的答案
GetDog
应该抛出异常。这是一个糟糕的设计。在此类中,并非所有
NullReferenceException
都应转换为
DogDoesNotExistException
。这很容易出错。你需要直言不讳。您真的需要抛出异常吗?如果原因是异常冒泡并在不同的层上处理,那么OK,但为什么不使用TryXXX模式返回布尔值?好的,我将更新我的问题您不能这样做。你没有这种程度的控制。异常是在系统的内部深处生成的