C# 中如果不为 null 则调用方法
是否有可能以某种方式缩短这个声明?
if (obj != null)
obj.SomeMethod();
因为我碰巧写了很多这样的东西,这很烦人。 我唯一能想到的就是实现空对象模式,但这不是我每次都能做的,而且它当然不是缩短语法的解决方案。
与事件类似的问题,
public event Func<string> MyEvent;
然后调用
if (MyEvent != null)
MyEvent.Invoke();
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 Object pattern, 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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
从 C# 6 开始,您可以只使用:
或:
?.
是 null 传播运算符,并且会导致.Invoke()
在以下情况下短路:操作数为null
。 操作数仅被访问一次,因此不存在“检查和调用之间的值变化”问题的风险。===
在 C# 6 之前,不存在:没有空安全魔法,但有一个例外; 扩展方法 - 例如:
现在这是有效的:
在事件的情况下,这具有还删除竞争条件的优点,即您不需要临时变量。 所以通常你需要:
但使用:
我们可以简单地使用:
From C# 6 onwards, you can just use:
or:
The
?.
is the null-propagating operator, and will cause the.Invoke()
to be short-circuited when the operand isnull
. The operand is only accessed once, so there is no risk of the "value changes between check and invoke" problem.===
Prior to C# 6, no: there is no null-safe magic, with one exception; extension methods - for example:
now this is valid:
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:
but with:
we can use simply:
您正在寻找的是 空条件(不是“合并”)运算符:
?.
。 它从 C# 6 开始可用。您的示例为
obj?.SomeMethod();
。 如果 obj 为 null,则不会发生任何事情。 当方法有参数时,例如obj?.SomeMethod(new Foo(), GetBar());
如果obj
为 null,则不会评估参数,这在评估时很重要这些论点会产生副作用。并且链接是可能的:
myObject?.Items?[0]?.DoSomething()
What you're looking for is the Null-Conditional (not "coalescing") operator:
?.
. It's available as of 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 ifobj
is null, which matters if evaluating the arguments would have side effects.And chaining is possible:
myObject?.Items?[0]?.DoSomething()
快速扩展方法:
example:
或者:
example:
A quick extension method:
example:
or alternatively:
example:
事件可以使用空的默认委托进行初始化,该委托永远不会被删除:
无需进行空检查。
[更新,感谢 Bevan 指出这一点]
不过,请注意可能的性能影响。 我所做的一个快速微基准测试表明,使用“默认委托”模式时,处理没有订阅者的事件会慢 2-3 倍。 (在我的双核 2.5GHz 笔记本电脑上,这意味着 279 毫秒:筹集 5000 万个未订阅事件需要 785 毫秒。)。 对于应用程序热点,这可能是一个需要考虑的问题。
Events can be initialized with an empty default delegate which is never removed:
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.
是的,在 C# 6.0 中 -- https://msdn.microsoft.com/en-我们/杂志/dn802602.aspx。
Yes, in C# 6.0 -- https://msdn.microsoft.com/en-us/magazine/dn802602.aspx.
Ian Griffiths 的这篇文章给出了两种不同的方法他总结出的问题解决方案是你不应该使用的巧妙技巧。
This article by Ian Griffiths gives two different solutions to the problem that he concludes are neat tricks that you should not use.
像有人建议的那样,建立扩展方法并不能真正解决竞争条件问题,而是隐藏它们。
如前所述,这段代码与临时变量的解决方案是优雅的等价物,但是...
两者的问题事件的订阅者可能会在取消事件订阅后被调用。 这是可能的,因为取消订阅可能发生在将委托实例复制到临时变量(或作为上述方法中的参数传递)之后、调用委托之前。
一般来说,在这种情况下客户端代码的行为是不可预测的:组件状态已经不允许处理事件通知。 可以以处理它的方式编写客户端代码,但这会给客户端带来不必要的责任。
确保线程安全的唯一已知方法是对事件发送者使用锁定语句。 这可确保所有订阅\取消订阅\调用均已序列化。
为了更准确,锁定应该应用于添加\删除事件访问器方法中使用的同一同步对象,默认为“this”。
Cerating extention method like one suggested does not really solve issues with race conditions, but rather hide them.
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.
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'.
我同意肯尼·埃利亚松的回答。 使用扩展方法。 以下是扩展方法和所需的 IfNotNull 方法的简要概述。
扩展方法( IfNotNull 方法)
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.
Extension Methods ( IfNotNull method )
也许不是更好,但在我看来更具可读性的是创建一个扩展方法
Maybe not better but in my opinion more readable is to create an extension method
我已经制作了我使用的通用扩展。
然后我像下面一样使用它。
I have made this generic extension that I use.
Then I use it like below.
C# 中有一个鲜为人知的空运算符 ??。 可能会有所帮助:
http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with- linq.aspx
There is a little-known null operator in C# for this, ??. May be helpful:
http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx