Esta pregunta surge ocasionalmente, pero no he visto una respuesta satisfactoria.
Un patrón típico es (la fila es una DataRow ):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
Mi primera pregunta es cuál es más eficiente (he cambiado la condición):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Esto indica que .GetType () debería ser más rápido, pero ¿tal vez el compilador conoce algunos trucos que yo no?
Segunda pregunta, ¿vale la pena almacenar en caché el valor de la fila ["valor"] o el compilador optimiza el indexador de todos modos?
Por ejemplo:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Notas:
- la fila ["valor"] existe.
- No sé el índice de columna de la columna (de ahí la búsqueda del nombre de la columna).
- Estoy preguntando específicamente sobre la comprobación de DBNull y luego la asignación (no sobre la optimización prematura, etc.).
Comparé algunos escenarios (tiempo en segundos, 10,000,000 pruebas):
row["value"] == DBNull.Value: 00:00:01.5478995
row["value"] is DBNull: 00:00:01.6306578
row["value"].GetType() == typeof(DBNull): 00:00:02.0138757
Object.ReferenceEquals tiene el mismo rendimiento que "=="
¿El resultado más interesante? Si no coincide el nombre de la columna por caso (por ejemplo, "Valor" en lugar de "valor", se tarda aproximadamente diez veces más (para una cadena):
row["Value"] == DBNull.Value: 00:00:12.2792374
La moraleja de la historia parece ser que si no puede buscar una columna por su índice, asegúrese de que el nombre de la columna que alimenta al indexador coincida exactamente con el nombre de la columna de datos.
El almacenamiento en caché del valor también parece ser casi el doble de rápido:
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Entonces, el método más eficiente parece ser:
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}
IDataRecord
extensiones.