我最近就这个主题提出了this question,该主题已被关闭为this one的副本 - 与我之前的this one一样。但是,我想在一个角落案例中提出一个更具体的问题,我觉得上述问题或答案中没有一个真正涵盖:
实际上不需要实例的扩展方法应该如何响应空引用?
一个例子(答案显而易见)将是.IsNullOrEmpty()
(当然应该只返回空引用上的true
),但我相信可能还有其他一些有意义的情况在可能为null的对象上调用扩展方法。
另一个例子可能是我在my other question中概述的方法的变体,如果我们暂时假设foreach
循环不会抛出空集合(我知道它确实如此,但想象一下)它不仅仅是一个思想实验。)
这里最好的做法是什么?我们应该检查null并抛出ArgumentNullException
,还是取决于案例?如果确实取决于具体情况,我们应该根据什么标准决定做什么?
答案 0 :(得分:7)
就个人而言,我遇到的问题是扩展方法没有抛出null实例。我知道扩展方法是静态方法的语法糖。但是,它们的使用类似于实例方法。因此,我认为它们应该表现得像是一个实例方法,并在“this”实例为null时抛出。
这对我来说是一个可维护性问题。对于不知道方法是在实际类型上还是扩展方法的代码库的新手,看到像IsNull()这样的方法会令人不安,因为它根本没有任何意义。
所以,这是我的两分钱:一个完整的个人观点。
答案 1 :(得分:2)
如果我理解正确,那就是你所说的:
public class MyClass
{
....
}
public static class MyClassExtension
{
public static void MyClassExtensionMethod1(this MyClass obj, string name)
{
if(obj == null)
{
// what to do here, since obj is not used anywhere in this method
}
Console.WriteLine(name);
}
}
我认为这取决于你的思想流派。
由于MyClassExtensionMethod1
根本不使用MyClass
对象,因此您可以跳过检查,并跳过通知客户端代码(或用户)。
在进一步讨论之前,我会问自己,如果它没有引用传入的类的实例,那么首先使用这个扩展方法有什么意义呢?
我建议采用以下两种方法之一:
如果您可以修改代码,并且此方法属于MyClass,请在MyClass
中创建MyClassExtensionMethod1方法。当然,这意味着实例不会为null,因此您正在改变您的期望:)
public class MyClass
{
...
public MyClassMethod1(string name)
{
Console.WriteLine(name);
}
}
...或者,如果您确实不需要MyClass实例,请将此方法移至另一个类,与MyClass
无关:
// not an extension class
public class MyOtherClass
{
public void MyOtherClassMethod1(string name)
{
Console.WriteLine(name);
}
}
即使您保留了扩展方法(以及是否抛出),我建议您在决定时添加好文档,以备将来参考。
答案 2 :(得分:0)
以下是我有意引入扩展方法来处理null
的示例。
public class Foo {
public int Time { get; set; }
}
public static class ExtensionMethods {
public static int? GetNullableTime(this Foo foo) {
if (foo == null) return null; // Cast is implicit.
return foo.Time;
}
}
当你在一些属性初始化程序中使用它时,它会很好。你告诉我什么看起来更好。
var b1 = new Bar{
T1 = (foo1 == null) ? (int?)null : foo1.Time, // Note, cast is *required*
T2 = (foo2 == null) ? (int?)null : foo2.Time,
T3 = (foo3 == null) ? (int?)null : foo3.Time,
};
var b2 = new Bar{
T1 = foo1.GetNullableTime(),
T2 = foo2.GetNullableTime(),
T3 = foo3.GetNullableTime(),
};