在 C# 中如果不为 null 的方法调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/872323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Method call if not null in C#
提问by Jakub Arnold
Is it possible to somehow shorten this statement?
是否有可能以某种方式缩短此声明?
if (obj != null)
obj.SomeMethod();
because I happen to write this a lot and it gets pretty annoying. The only thing I can think of is to implement Null Objectpattern, but that's not what I can do every time and it's certainly not a solution to shorten syntax.
因为我碰巧写了很多,这很烦人。我唯一能想到的就是实现空对象模式,但这不是我每次都能做的,当然也不是缩短语法的解决方案。
And similar problem with events, where
和事件类似的问题,其中
public event Func<string> MyEvent;
and then invoke
然后调用
if (MyEvent != null)
MyEvent.Invoke();
采纳答案by Marc Gravell
From C# 6 onwards, you can just use:
从 C# 6 开始,您可以使用:
MyEvent?.Invoke();
or:
或者:
obj?.SomeMethod();
The ?.
is the null-propagating operator, and will cause the .Invoke()
to be short-circuited when the operand is null
. The operand is only accessed once, so there is no risk of the "value changes between check and invoke" problem.
的?.
是null传播算子,并且将导致.Invoke()
要被短路时的操作数是null
。操作数只访问一次,因此不存在“检查和调用之间的值更改”问题的风险。
===
===
Prior to C# 6, no: there is no null-safe magic, with one exception; extension methods - for example:
在 C# 6 之前,不:没有空安全魔法,只有一个例外;扩展方法 - 例如:
public static void SafeInvoke(this Action action) {
if(action != null) action();
}
now this is valid:
现在这是有效的:
Action act = null;
act.SafeInvoke(); // does nothing
act = delegate {Console.WriteLine("hi");}
act.SafeInvoke(); // writes "hi"
In the case of events, this has the advantage of also removing the race-condition, i.e. you don't need a temporary variable. So normally you'd need:
在事件的情况下,这还具有消除竞争条件的优点,即您不需要临时变量。所以通常你需要:
var handler = SomeEvent;
if(handler != null) handler(this, EventArgs.Empty);
but with:
但与:
public static void SafeInvoke(this EventHandler handler, object sender) {
if(handler != null) handler(sender, EventArgs.Empty);
}
we can use simply:
我们可以简单地使用:
SomeEvent.SafeInvoke(this); // no race condition, no null risk
回答by Kenny Eliasson
Maybe not better but in my opinion more readable is to create an extension method
也许不是更好,但在我看来更具可读性的是创建一个扩展方法
public static bool IsNull(this object obj) {
return obj == null;
}
回答by Sven Künzler
Events can be initialized with an empty default delegate which is never removed:
事件可以用一个永远不会被删除的空默认委托进行初始化:
public event EventHandler MyEvent = delegate { };
No null-checking necessary.
不需要空检查。
[Update, thanks to Bevan for pointing this out]
[更新,感谢贝文指出这一点]
Be aware of the possible performance impact, though. A quick micro benchmark I did indicates that handling an event with no subscribers is 2-3 times slower when using the the "default delegate" pattern. (On my dual core 2.5GHz laptop that means 279ms : 785ms for raising 50 million not-subscribed events.). For application hot spots, that might be an issue to consider.
但是,请注意可能的性能影响。我所做的一个快速微基准测试表明,在使用“默认委托”模式时,处理没有订阅者的事件要慢 2-3 倍。(在我的双核 2.5GHz 笔记本电脑上,这意味着 279 毫秒:785 毫秒用于引发 5000 万个未订阅事件。)。对于应用热点,这可能是一个需要考虑的问题。
回答by Darrel Miller
回答by Matt Sherman
There is a little-known null operator in C# for this, ??. May be helpful:
C#中有一个鲜为人知的空操作符,??。可能有帮助:
回答by andrey.tsykunov
Cerating extention method like one suggested does not really solve issues with race conditions, but rather hide them.
像有人建议的 Cering 扩展方法并没有真正解决竞争条件的问题,而是隐藏它们。
public static void SafeInvoke(this EventHandler handler, object sender)
{
if (handler != null) handler(sender, EventArgs.Empty);
}
As stated this code is the elegant equivalent to solution with temporary variable, but...
如上所述,此代码与具有临时变量的解决方案优雅等效,但是......
The problem with both that it's possible that subsciber of the event could be called AFTER it has unsubscribed from the event. This is possible because unsubscription can happen after delegate instance is copied to the temp variable (or passed as parameter in the method above), but before delegate is invoked.
两者的问题是,事件的订阅者可能会在取消订阅事件后被调用。这是可能的,因为在将委托实例复制到临时变量(或在上述方法中作为参数传递)之后,但在调用委托之前,可能会发生取消订阅。
In general the behaviour of the client code is unpredictable in such case: component state could not allow to handle event notification already. It's possible to write client code in the way to handle it, but it would put unnecesssary responsibility to the client.
通常,在这种情况下客户端代码的行为是不可预测的:组件状态已经不允许处理事件通知。可以按照处理它的方式编写客户端代码,但这会给客户端带来不必要的责任。
The only known way to ensure thread safity is to use lock statement for the sender of the event. This ensures that all subscriptions\unsubscriptions\invocation are serialized.
确保线程安全的唯一已知方法是对事件的发送者使用 lock 语句。这确保所有订阅\取消订阅\调用都被序列化。
To be more accurate lock should be applied to the same sync object used in add\remove event accessor methods which is be default 'this'.
为了更准确,锁定应该应用于添加\删除事件访问器方法中使用的相同同步对象,这是默认的“this”。
回答by Rohit
I agree with the answer by Kenny Eliasson. Go with Extension methods. Here is a brief overview of extension methods and your required IfNotNull method.
我同意 Kenny Eliasson 的回答。使用扩展方法。这是扩展方法和您所需的 IfNotNull 方法的简要概述。
回答by katbyte
A quick extension method:
一种快速扩展方法:
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();
}
}
example:
例子:
string str = null;
str.IfNotNull(s => Console.Write(s.Length));
str.IfNotNull(s => Console.Write(s.Length), () => Console.Write("null"));
or alternatively:
或者:
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));
}
example:
例子:
string str = null;
Console.Write(str.IfNotNull(s => s.Length.ToString());
Console.Write(str.IfNotNull(s => s.Length.ToString(), () => "null"));
回答by Vimes
What you're looking for is the Null Conditional(not "coalescing") operator: ?.
. It's available as of C# 6.
您正在寻找的是Null 条件(不是“合并”)运算符:?.
。它从 C# 6 开始可用。
Your example would be obj?.SomeMethod();
. If obj is null, nothing happens. When the method has arguments, e.g. obj?.SomeMethod(new Foo(), GetBar());
the arguments are not evaluated if obj
is null, which matters if evaluating the arguments would have side effects.
你的例子是obj?.SomeMethod();
. 如果 obj 为空,则什么也不会发生。当方法有参数时,例如obj?.SomeMethod(new Foo(), GetBar());
,如果obj
为 null,则不评估参数,如果评估参数会产生副作用,这很重要。
And chaining is possible: myObject?.Items?[0]?.DoSomething()
并且链接是可能的: myObject?.Items?[0]?.DoSomething()
回答by epylar
Yes, in C# 6.0 -- https://msdn.microsoft.com/en-us/magazine/dn802602.aspx.
是的,在 C# 6.0 中——https: //msdn.microsoft.com/en-us/magazine/dn802602.aspx。
object?.SomeMethod()