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
}
答案 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实例的上下文中使用该方法,则根本不检查它无论如何应该在身边。
如果你实际上没有狗,你就不会去你的柜子里拿出狗食并把它放在碗里。如果你已经知道你有一只狗,你只能得到并准备食物。
因此,如果您没有狗(FeedDog
为dog
),则不会致电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
}