¿Lanzar un nulo en algo?

Tuve esta interesante discusión hoy con un colega. Estábamos debatiendo dos piezas de código en C #.

Fragmento de código 1:

if(!reader.IsDBNull(2)) { long? variable1 = reader.GetInt64(2) } 

Fragmento de código 2:

 long variable1 = reader.IsDBNull(2) ? (long?) null : reader.GetInt64(2) 

La pregunta es: ¿es una buena práctica convertir nulo en un anulable largo? O preferirías usar la instrucción if tradicional para evitar la conversión de valores null a null durante mucho tiempo.

Las expresiones (type?)null , default(type?) Y el new Nullable() se comstackn en los mismos new Nullable() :

  long? x = (long?)null; long? y = default(long?); long? z = new Nullable(); 

se convierte en

  IL_0001: ldloca.sx IL_0003: initobj valuetype [mscorlib]System.Nullable`1 IL_0009: ldloca.sy IL_000b: initobj valuetype [mscorlib]System.Nullable`1 IL_0011: ldloca.sz IL_0013: initobj valuetype [mscorlib]System.Nullable`1 

En otras palabras, si trabaja con tipos que admiten nulos, puede utilizar la versión que más le guste. Tenga en cuenta, sin embargo, que debe intentar evitar la aritmética con tipos anulables. Si desea devolver un valor anulable desde una expresión condicional, ambos resultados posibles deben ser anulables si uno de ellos puede ser nulo. Cualquier otra forma podría causar una excepción en ese caso.

En lugar de

 (long?) null 

utilizar

 default(long?) 

Me gustaría refactorizar el código anterior

 long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2) 

Prefiero no lanzar valor null (me parece extraño):

 long? variable1 = reader.IsDBNull(2) ? null : (long?)reader.GetInt64(2); 

Otras opciones:

 long? variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2); // requires C# 7.1 long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2); long? variable1 = reader.IsDBNull(2) ? (long?)null : reader.GetInt64(2); long? variable1 = reader.IsDBNull(2) ? new Nullable() : reader.GetInt64(2); long? variable1 = reader.IsDBNull(2) ? new long?() : reader.GetInt64(2); long? variable1 = reader.IsDBNull(2) ? null : new long?(reader.GetInt64(2)); 

Es solo cuestión de gustos. Creo que la primera opción es más legible, que otras.

ACTUALIZACIÓN: Considere también escribir algunos métodos de extensión para que su código sea más claro:

 public static class DataReaderExtensions { public static long? GetNullableInt64(this IDataReader reader, int index) { if (reader.IsDBNull(index)) return null; return reader.GetInt64(index); } } 

En este caso, no utiliza el operador ternario (no se puede convertir a Nullable), y la lectura de los valores del lector se ve más bonita:

 long? variable1 = reader.GetNullableInt64(2); 

El fragmento 2 vale en mi caso, ya que en caso de null , obtendrás 0 , que es un valor completamente válido por long

En C # 7.1 puedes usar el literal por default más conciso :

 var variable1 = reader.IsDBNull(2) ? default : reader.GetInt64(2);