¿Es posible acortar de alguna manera esta afirmación?
if (obj != null)
obj.SomeMethod();
porque escribo esto mucho y se vuelve bastante molesto. Lo único que se me ocurre es implementar un objeto nulo patrón de , pero eso no es lo que puedo hacer siempre y ciertamente no es una solución para acortar la sintaxis.
Y un problema similar con los eventos, donde
public event Func<string> MyEvent;
y luego invocar
if (MyEvent != null)
MyEvent.Invoke();
Respuestas:
Desde C # 6 en adelante, puede usar:
o:
El
?.
es el operador de propagación nula, y provocará.Invoke()
un cortocircuito cuando el operando esténull
. Solo se accede al operando una vez, por lo que no hay riesgo de que se produzca el problema de "cambios de valor entre verificación e invocación".===
Antes de C # 6, no: no hay magia segura para nulos, con una excepción; métodos de extensión, por ejemplo:
ahora esto es válido:
En el caso de los eventos, esto tiene la ventaja de eliminar también la condición de carrera, es decir, no necesita una variable temporal. Entonces, normalmente necesitarías:
pero con:
podemos usar simplemente:
fuente
?.
- en VB14 y superiorLo que estamos buscando es el condicional nulo (no "coalescencia") del operador:
?.
. Está disponible a partir de C # 6.Tu ejemplo sería
obj?.SomeMethod();
. Si obj es nulo, no sucede nada. Cuando el método tiene argumentos, por ejemplo,obj?.SomeMethod(new Foo(), GetBar());
los argumentos no se evalúan siobj
es nulo, lo que importa si la evaluación de los argumentos tendría efectos secundarios.Y el encadenamiento es posible:
myObject?.Items?[0]?.DoSomething()
fuente
Un método de extensión rápido:
ejemplo:
o alternativamente:
ejemplo:
fuente
Los eventos se pueden inicializar con un delegado predeterminado vacío que nunca se elimina:
No se necesita verificación de nulos.
[ Actualización , gracias a Bevan por señalar esto]
Sin embargo, tenga en cuenta el posible impacto en el rendimiento. Un micro benchmark rápido que hice indica que manejar un evento sin suscriptores es 2-3 veces más lento cuando se usa el patrón de "delegado predeterminado". (En mi portátil de 2,5 GHz de doble núcleo, eso significa 279 ms: 785 ms para generar 50 millones de eventos no suscritos). Para los puntos calientes de la aplicación, ese podría ser un tema a considerar.
fuente
Sí, en C # 6.0 - https://msdn.microsoft.com/en-us/magazine/dn802602.aspx .
fuente
Este artículo de Ian Griffiths ofrece dos soluciones diferentes al problema que, según él, son trucos ingeniosos que no debes usar.
fuente
Cerar el método de extensión como el sugerido no resuelve realmente los problemas con las condiciones de carrera, sino que los oculta.
Como se dijo, este código es el equivalente elegante a la solución con variable temporal, pero ...
El problema con ambos es que es posible que el suscriptor del evento se llame DESPUÉS de que se haya cancelado la suscripción del evento . Esto es posible porque la cancelación de la suscripción puede ocurrir después de que la instancia de delegado se copia a la variable temporal (o se pasa como parámetro en el método anterior), pero antes de que se invoque al delegado.
En general, el comportamiento del código del cliente es impredecible en tal caso: el estado del componente ya no podía permitir manejar la notificación de eventos. Es posible escribir el código del cliente en la forma de manejarlo, pero le pondría una responsabilidad innecesaria al cliente.
La única forma conocida de garantizar la seguridad del hilo es utilizar la declaración de bloqueo para el remitente del evento. Esto asegura que todas las suscripciones \ cancelaciones de suscripción \ invocaciones estén serializadas.
Para ser más preciso, el bloqueo debe aplicarse al mismo objeto de sincronización utilizado en los métodos de acceso de evento add / remove, que es el predeterminado 'this'.
fuente
Estoy de acuerdo con la respuesta de Kenny Eliasson. Vaya con los métodos de extensión. Aquí hay una breve descripción general de los métodos de extensión y el método IfNotNull requerido.
Métodos de extensión (método IfNotNull)
fuente
Tal vez no sea mejor, pero en mi opinión es más legible crear un método de extensión.
fuente
return obj == null
significa. ¿Qué devolveráobj
es así,null
el método volverátrue
, creo.null
? Estoy bastante seguro de que esto no funciona con los métodos propios del tipo, por lo que dudo que funcione tampoco con los métodos de extensión. Creo que la mejor forma de comprobar si un objeto lo esnull
esobj is null
. Desafortunadamente, para verificar si un objeto no lo es, esnull
necesario envolverlo entre paréntesis, lo cual es desafortunado.Hay un operador nulo poco conocido en C # para esto, ??. Puede ser útil:
http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx
fuente