2012-08-14 34 views
8

tengo una costumbre WebControl que implementa un .Value captador/definidor devolver un <decimal>Comprender el operador coalescente nula (??)

Es un cuadro de texto filtrado del lado del cliente anulable (una subclase de TextBox con incluida javascript y algo de lógica del lado del servidor para establecer/obtener el valor)

Aquí está el captador & la incubadora de ese control:

public decimal? Value 
{ 
    get 
    { 
     decimal amount = 0; 
     if (!decimal.TryParse(this.Text, NumberStyles.Currency, null, out amount)) 
     { 
      return null; 
     } 
     else 
     { 
      return amount; 
     } 
    } 
    set 
    { 
     if (!value.HasValue) 
     { 
      this.Text = ""; 
     } 
     else 
     { 
      this.Text = string.Format("${0:#,##0.00}", value); 
     } 
    } 
} 

El problema que veo es que la salida de esta declaración:

decimal Amount = uxAmount.Value ?? 0M; 

estoy viendo cantidad que se establece en "0" cuando vuelve uxAmount.Value 10000.

Esto funcionó como esperaba (excusa el cambio en la carcasa):

decimal? _Amount = uxAmount.Value; 
decimal amount = _Amount ?? 0; 

también he visto este comportamiento (recientemente) cuando se llama a una función UDF definido en un contexto de datos Linq2Sql junto con el operador coalescente nula, es decir sabía que mi llamada UDF devolvió el esperado valor, pero yo era ge tting el valor RHS en su lugar.

Me confunde aún más, si evalúo uxAmount.Value en el reloj, obtengo 10000 de tipo Nullable<decimal>.

Estas son algunas de las expresiones que he probado:

decimal? _Amount = uxAmount.Value; //10000 
decimal amount = _Amount ?? 0; //10000 
decimal amount2 = _Amount ?? 0M; //10000 
decimal Amount = uxAmount.Value ?? 0M; //0 

Luego añade esta expresión después de la anterior 4

decimal amount3 = (uxTaxAmount.Value) ?? 0M; 

Ahora

decimal Amount = uxAmount.Value ?? 0M; //10000 
decimal amount3 = (uxAmount.Value) ?? 0M; //0 

Parece que la última llamada siempre es 0, pero el valor de uxAmount.Value (que se analiza de .Text según el getter/setter anterior usando un TryParse es estable. Estoy detenido en un punto de interrupción y no hay otros hilos que puedan manipular este valor.

Tenga en cuenta el uso del sufijo M para forzar la constante a decimal ya que era un número entero y sospechaba que había un problema de conversión de tipo.

¿Alguna idea?

El valor de LHS y RHS parece ser estable y conocido.

--edit-- algunos screengrabs de VS2010

Stepping through the code showing the value of amount3

Watch dialog and some more detail about state of variables

+0

CurrencyTextBox (una subclase de TextBox) – agrath

+1

Es un decimal que se puede nulos [decimal?] - vea la definición de getter/setter en la parte superior de la pregunta – agrath

+1

¿Está seguro de que el depurador le muestra esto correctamente? ¿Has intentado caminar algunas líneas más abajo para asegurarte de que tienes el valor actualizado de 'amount3'? Porque cuando 'XXX' es un decimal con nulo, entonces' XXX ?? 0M' será un decimal (no anulable) que tendrá el valor de 'XXX' si no es nulo, y el valor cero en caso contrario. –

Respuesta

0

(Esta respuesta fue construido a partir de mis comentarios anteriores.)

¿Seguro de los dsiplays depurador esto correctamente para usted? ¿Has intentado caminar algunas líneas más abajo para asegurarte de que tienes el valor actualizado de amount3?

Estoy seguro de que es solo un problema con el depurador. A veces tienes que dar un paso más. Tal vez el código traducido (IL) tiene algunas optimizaciones que confunden al depurador (o lo que sé). Pero sin el depurador, el valor se actualizará exactamente cuando lo espere.

He visto a otros desarrolladores experimentados estar confundidos por situaciones similares, así que sé que el depurador a veces es "una línea de código" detrás cuando se mira una asignación a una variable local. ¿Tal vez alguien puede encontrar un enlace discutiendo eso?

1

Echa un vistazo a esta pregunta similar

using coalescing null operator on nullable types changes implicit type

¿por qué no hacer

decimal amount = uxTaxAmount.Value.HasValue ? uxTaxAmount.Value.Value : 0M 

Esta no es la respuesta correcta a los problemas de los carteles originales debido a ediciones y comentarios recientes.

+0

Resulta que es un problema de depuración.Estaba muy preocupado de que mi uso de ?? tenía muchos efectos secundarios desconocidos y tenía que revisar todos mis proyectos y asegurarme de haber cambiado la sintaxis – agrath

+0

. Además, .Valor es decimal? (Nullable ) – agrath

+0

oh No hice esa conexión, ya que es un decimal con nulo el valor real sería Value.Value :) –

Cuestiones relacionadas