Questa domanda si presenta occasionalmente, ma non ho visto una risposta soddisfacente.
Un modello tipico è (la riga è un DataRow ):
if (row["value"] != DBNull.Value)
{
someObject.Member = row["value"];
}
La mia prima domanda è quale sia più efficiente (ho capovolto la condizione):
row["value"] == DBNull.Value; // Or
row["value"] is DBNull; // Or
row["value"].GetType() == typeof(DBNull) // Or... any suggestions?
Ciò indica che .GetType () dovrebbe essere più veloce, ma forse il compilatore conosce alcuni trucchi, no?
Seconda domanda, vale la pena memorizzare nella cache il valore di riga ["valore"] o il compilatore ottimizza comunque l'indicizzatore?
Per esempio:
object valueHolder;
if (DBNull.Value == (valueHolder = row["value"])) {}
Appunti:
- riga ["valore"] esiste.
- Non conosco l'indice di colonna della colonna (da qui la ricerca del nome della colonna).
- Sto chiedendo in particolare il controllo di DBNull e quindi dell'assegnazione (non dell'ottimizzazione prematura, ecc.).
Ho analizzato alcuni scenari (tempo in secondi, 10.000.000 di prove):
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 ha le stesse prestazioni di "=="
Il risultato più interessante? Se non si corrisponde il nome della colonna per caso (ad esempio, "Valore" anziché "valore", impiega circa dieci volte più a lungo (per una stringa):
row["Value"] == DBNull.Value: 00:00:12.2792374
La morale della storia sembra essere che se non riesci a cercare una colonna dal suo indice, assicurati che il nome della colonna che dai all'indicizzatore corrisponda esattamente al nome del DataColumn.
Anche la memorizzazione nella cache del valore sembra essere quasi il doppio più veloce:
No Caching: 00:00:03.0996622
With Caching: 00:00:01.5659920
Quindi il metodo più efficiente sembra essere:
object temp;
string variable;
if (DBNull.Value != (temp = row["value"]))
{
variable = temp.ToString();
}
IDataRecord
estensioni.