方法调用,如果在C#中不为空
是否有可能以某种方式缩短这个陈述?
if (obj != null) obj.SomeMethod(); 因为我碰巧写了很多,而且非常恼人。 我唯一能想到的是实现Null对象模式,但这不是我每次都能做到的,当然也不是缩短语法的解决scheme。
与事件类似的问题,在哪里
 public event Func<string> MyEvent; 
然后调用
 if (MyEvent != null) MyEvent.Invoke(); 
	
从C#6开始,您可以使用:
 MyEvent?.Invoke(); 
要么:
 obj?.SomeMethod(); 
 那个?. 是空传播运算符,当操作数为null时,会导致.Invoke()短路。 操作数只被访问一次,所以没有“检查和调用之间的值变化”问题的风险。 
===
在C#6之前,不:没有无效的魔法,只有一个例外; 扩展方法 – 例如:
 public static void SafeInvoke(this Action action) { if(action != null) action(); } 
现在这是有效的:
 Action act = null; act.SafeInvoke(); // does nothing act = delegate {Console.WriteLine("hi");} act.SafeInvoke(); // writes "hi" 
在事件的情况下,这也具有消除竞争条件的优点,即不需要临时variables。 所以通常你需要:
 var handler = SomeEvent; if(handler != null) handler(this, EventArgs.Empty); 
但是:
 public static void SafeInvoke(this EventHandler handler, object sender) { if(handler != null) handler(sender, EventArgs.Empty); } 
我们可以简单地使用:
 SomeEvent.SafeInvoke(this); // no race condition, no null risk 
 你正在寻找的是空条件 (而不是“合并”)运算符: ?.  。 它从C#6开始提供。 
 你的例子是obj?.SomeMethod();  。 如果obj为null,则不会发生任何事情。 当方法有参数时,例如obj?.SomeMethod(new Foo(), GetBar()); 如果obj为null,则不会评估参数,如果评估参数会产生副作用,则该参数很重要。 
 链接是可能的: myObject?.Items?[0]?.DoSomething() 
快速扩展方法:
  public static void IfNotNull<T>(this T obj, Action<T> action, Action actionIfNull = null) where T : class { if(obj != null) { action(obj); } else if ( actionIfNull != null ) { actionIfNull(); } } 
例:
  string str = null; str.IfNotNull(s => Console.Write(s.Length)); str.IfNotNull(s => Console.Write(s.Length), () => Console.Write("null")); 
或者可选地:
  public static TR IfNotNull<T, TR>(this T obj, Func<T, TR> func, Func<TR> ifNull = null) where T : class { return obj != null ? func(obj) : (ifNull != null ? ifNull() : default(TR)); } 
例:
  string str = null; Console.Write(str.IfNotNull(s => s.Length.ToString()); Console.Write(str.IfNotNull(s => s.Length.ToString(), () => "null")); 
是的,在C#6.0中 – https://msdn.microsoft.com/en-us/magazine/dn802602.aspx 。
 object?.SomeMethod() 
事件可以用一个永远不会被删除的空的默认委托进行初始化:
 public event EventHandler MyEvent = delegate { }; 
没有必要的空检查。
[ 更新 ,感谢Bevan指出了这一点]
但要注意可能的性能影响。 我所做的一个快速微型基准testing表明,使用“默认代理”模式时,处理没有订阅者的事件速度要慢2-3倍。 (在我的双核2.5GHz笔记本电脑上,这意味着279毫秒:785毫秒提高5000万未订阅的事件)。 对于应用热点,这可能是一个需要考虑的问题。
这篇由伊恩·格里菲斯(Ian Griffiths)撰写的文章给出了两个不同的解决scheme,他总结的是不应该使用的巧妙技巧。
像一个Cerate扩展方法build议并不真正解决竞争条件的问题,而是隐藏它们。
 public static void SafeInvoke(this EventHandler handler, object sender) { if (handler != null) handler(sender, EventArgs.Empty); } 
如上所述,这个代码是与临时variables解决scheme相当的优雅,但…
两个问题都有可能,那就是事件的子事件可能会在事件取消订阅之后被调用 。 这是可能的,因为在委托实例复制到tempvariables(或者在上面的方法中作为parameter passing)之后,但在调用delegate之前,取消订阅可能发生。
一般来说,在这种情况下,客户端代码的行为是不可预知的:组件状态不允许已经处理事件通知。 可以用处理它的方式编写客户端代码,但是会给客户端带来不必要的责任。
确保线程安全性的唯一已知方法是使用locking语句作为事件的发送者。 这可确保所有订阅\取消订阅\调用都被序列化。
为了更准确的locking,应该应用到add \ remove事件访问器方法中使用的同一个同步对象,它是默认的“this”。
我同意Kenny Eliasson的回答。 使用扩展方法。 以下是扩展方法和您所需的IfNotNull方法的简要概述。
扩展方法(IfNotNull方法)
也许不会更好,但在我看来更可读的是创build一个扩展方法
 public static bool IsNull(this object obj) { return obj == null; } 
在C#中有一个鲜为人知的null操作符。 可能有帮助: