c# - validar - no se puede convertir dbnull value al tipo system decimal utilice un tipo que acepte valores null
(esto== nulo) en C#! (6)
Debido a un error que se corrigió en C # 4, el siguiente programa imprime true
. (Pruébalo en LINQPad)
void Main() { new Derived(); }
class Base {
public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
string CheckNull() { return "Am I null? " + (this == null); }
public Derived() : base(() => CheckNull()) { }
}
En VS2008 en modo Release, arroja una InvalidProgramException. (En el modo de depuración, funciona bien)
En VS2010 Beta 2, no compila (no probé Beta 1); Aprendí que de la peor manera
¿Hay alguna otra manera de hacer this == null
en C # puro?
¡He tenido eso! (y obtuve pruebas también)
Esta observación se ha publicado en en otra pregunta el día de hoy.
La gran respuesta de Marc a esa pregunta indica que de acuerdo con la especificación (sección 7.5.7), no debería poder acceder a this
en ese contexto y la capacidad de hacerlo en el compilador C # 3.0 es un error. El compilador C # 4.0 se comporta correctamente según la especificación (incluso en la versión Beta 1, este es un error de tiempo de compilación):
§ 7.5.7 Este acceso
A this-access consiste en la palabra reservada
this
.este-acceso:
this
A este acceso solo se permite en el bloque de un constructor de instancia, un método de instancia o un descriptor de acceso de instancia.
Esto no es un "error". Esto es abusar del sistema de tipos. Nunca se supone que pases una referencia a la instancia actual ( this
) a nadie dentro de un constructor.
Podría crear un "error" similar llamando a un método virtual dentro del constructor de la clase base también.
El hecho de que puedas hacer algo malo no significa que sea un error cuando te muerde.
La descompilación sin procesar (reflector sin optimizaciones) del modo de depuración binario es:
private class Derived : Program.Base
{
// Methods
public Derived()
{
base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
return;
}
[CompilerGenerated]
private static string <.ctor>b__0()
{
string CS$1$0000;
CS$1$0000 = CS$1$0000.CheckNull();
Label_0009:
return CS$1$0000;
}
private string CheckNull()
{
string CS$1$0000;
CS$1$0000 = "Am I null? " + ((bool) (this == null));
Label_0017:
return CS$1$0000;
}
}
El método Generador de compilación no tiene sentido; si miras el IL (abajo), está llamando al método en una cadena nula (!).
.locals init (
[0] string CS$1$0000)
L_0000: ldloc.0
L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
L_0006: stloc.0
L_0007: br.s L_0009
L_0009: ldloc.0
L_000a: ret
En el modo Release, la variable local se optimiza, por lo que intenta enviar una variable inexistente a la pila.
L_0000: ldloc.0
L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
L_0006: ret
(El reflector se bloquea al convertirlo en C #)
EDITAR : ¿Alguien (Eric Lippert?) Sabe por qué el compilador emite el ldloc
?
No estoy seguro si esto es lo que estás buscando
public static T CheckForNull<T>(object primary, T Default)
{
try
{
if (primary != null && !(primary is DBNull))
return (T)Convert.ChangeType(primary, typeof(T));
else if (Default.GetType() == typeof(T))
return Default;
}
catch (Exception e)
{
throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
}
return default(T);
}
ejemplo: UserID = CheckForNull (Request.QueryString ["UserID"], 147);
Podría estar equivocado, pero estoy bastante seguro de que si su objeto es null
, nunca habrá un escenario donde this
aplique.
Por ejemplo, ¿cómo llamarías a CheckNull
?
Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException