Quiero hacer algo como esto:
myYear = record.GetValueOrNull<int?>("myYear"),
Observe el tipo anulable como parámetro genérico.
Como la GetValueOrNull
función podría devolver nulo, mi primer intento fue este:
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
Pero el error que obtengo ahora es:
El tipo 'int?' debe ser un tipo de referencia para usarlo como parámetro 'T' en el tipo o método genérico
¡Correcto! Nullable<int>
es un struct
! Así que intenté cambiar la restricción de clase a una struct
restricción (y como efecto secundario no puede volver null
más):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Ahora la tarea:
myYear = record.GetValueOrNull<int?>("myYear");
Da el siguiente error:
El tipo 'int?' debe ser un tipo de valor no anulable para poder usarlo como parámetro 'T' en el tipo o método genérico
¿Es posible especificar un tipo anulable como parámetro genérico?
IDataRecord
deDbDataRecord
..Respuestas:
Cambie el tipo de retorno a Nullable y llame al método con el parámetro no anulable
fuente
Solo úsalo así:
fuente
GetValueOrDefault
para aclarar que regresa endefault(T)
lugar de hacerlonull
. Alternativamente, podría hacer que arroje una excepción siT
no es anulable.Simplemente haga dos cosas a su código original: elimine la
where
restricción y cambie el últimoreturn
dereturn null
areturn default(T)
. De esta manera, puede devolver el tipo que desee.Por cierto, puede evitar el uso
is
cambiando suif
estado de cuenta aif (columnValue != DBNull.Value)
.fuente
return default
es suficiente (no necesita(T)
, el compilador lo inferirá del tipo de retorno de firma).Descargo de responsabilidad: esta respuesta funciona, pero tiene fines educativos únicamente. :) La solución de James Jones es probablemente la mejor aquí y ciertamente con la que yo iría.
La
dynamic
palabra clave de C # 4.0 hace esto aún más fácil, aunque menos seguro:Ahora no necesita la sugerencia de tipo explícito en el RHS:
De hecho, ¡ni siquiera lo necesitas!
value
ahora será un int, o una cadena, o cualquier tipo que se haya devuelto desde la base de datos.El único problema es que esto no le impide usar tipos no anulables en el LHS, en cuyo caso obtendrá una excepción de tiempo de ejecución bastante desagradable como:
Como con todo el código que usa
dynamic
: codificador de advertencia.fuente
Solo tenía que hacer algo increíble similar a esto. Mi código:
fuente
Creo que quieres manejar tipos de referencia y tipos de estructura. Lo uso para convertir cadenas de elementos XML a un tipo más tipeado. Puede eliminar la alternativa nula con reflexión. El proveedor de formato es manejar el dependiente de la cultura '.' o ',' separador en, por ejemplo, decimales o ints y dobles. Esto puede funcionar:
Puedes usarlo así:
fuente
Esto puede ser un hilo muerto, pero tiendo a usar lo siguiente:
fuente
Acabo de encontrar el mismo problema yo mismo.
... = reader["myYear"] as int?;
Funciona y está limpio.Funciona con cualquier tipo sin problemas. Si el resultado es DBNull, devuelve nulo cuando falla la conversión.
fuente
int v=reader["myYear"]??-1;
o algún otro valor predeterminado en lugar de-1
. Sin embargo, esto podría hacer referencia a cuestiones si el valor esDBNull
...Sé que esto es viejo, pero aquí hay otra solución:
Ahora, no le importa si
T
fue valor o tipo de referencia. Solo si la función devuelve verdadero, tiene un valor razonable de la base de datos. Uso:Este enfoque es muy similar a
int.TryParse("123", out MyInt);
fuente
Múltiples restricciones genéricas no se pueden combinar en forma OR (menos restrictiva), solo en forma AND (más restrictiva). Lo que significa que un método no puede manejar ambos escenarios. Las restricciones genéricas tampoco se pueden usar para hacer una firma única para el método, por lo que tendría que usar 2 nombres de métodos separados.
Sin embargo, puede usar las restricciones genéricas para asegurarse de que los métodos se usan correctamente.
En mi caso, específicamente quería que se devolviera nulo, y nunca el valor predeterminado de ningún tipo de valor posible. GetValueOrDefault = bad. GetValueOrNull = bueno.
Usé las palabras "Nulo" y "Nulable" para distinguir entre tipos de referencia y tipos de valor. Y aquí hay un ejemplo de un par de métodos de extensión que escribí que complementa el método FirstOrDefault en la clase System.Linq.Enumerable.
fuente
El camino más corto:
volver
0
paraint
ynull
paraint?
fuente