Pregunta

Estoy tratando de utilizar el operador condicional, pero me estoy haciendo colgó del tipo que piensa que el resultado debería ser.

A continuación se muestra un ejemplo que he ideado para mostrar el problema que estoy teniendo:

class Program
{
    public static void OutputDateTime(DateTime? datetime)
    {
        Console.WriteLine(datetime);
    }

    public static bool IsDateTimeHappy(DateTime datetime)
    {
        if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0)
            return true;

        return false;
    }

    static void Main(string[] args)
    {
        DateTime myDateTime = DateTime.Now;
        OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime);
        Console.ReadLine();                        ^
    }                                              |
}                                                  |
// This line has the compile issue  ---------------+

En la línea se ha indicado anteriormente, me sale el siguiente error de compilación:

Tipo de expresión condicional no se puede determinar porque no hay conversión implícita entre '' y 'System.DateTime'

Estoy confundido porque el parámetro es un tipo anulable (DateTime?). ¿Por qué necesita para convertir en absoluto? Si es nulo luego usar eso, si se trata de una fecha y hora que a continuación, utilizar.

Yo tenía la impresión de que:

condition ? first_expression : second_expression;

era el mismo que:

if (condition)
   first_expression;
else
   second_expression;

Es evidente que este no es el caso. ¿Cuál es el razonamiento detrás de esto?

(NOTA:.? Yo sé que si hago "MyDateTime" DateTime anulable entonces todo funcionará bien, pero ¿por qué lo necesito

Como dije anteriormente este es un ejemplo artificial. En mi ejemplo real "MyDateTime" es un dato de valor que no se puede hacer anulable mapeados.)

¿Fue útil?

Solución

El compilador no inferir el tipo del resultado del operador condicional de la utilización de los resultados, pero a partir de los tipos de sus argumentos. El compilador falla cuando se ve esta expresión porque no puede deducir el tipo del resultado:

IsDateTimeHappy(myDateTime) ? null : myDateTime;

Desde null y DateTime no son compatibles, es necesario indicar al compilador lo que debe ser el tipo. Un molde debe hacer el truco:

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);

Ahora el compilador no tendrá ningún problema. También puede escribir lo anterior en una línea, si lo prefiere (pero probablemente no podría hacer esto):

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);

Eric Lippert tiene un buena respuesta que también es relevante aquí y entra en más detalles acerca de cómo el compilador determina tipos.

Otros consejos

La razón es que el operador ternario espera que tanto los operandos sean del mismo tipo. Todo el get operador trabajó antes de que sea asignado a un resultado (en este caso pasó a una función), por lo que el compilador no puede saber lo que es el tipo de resultado.

IsDateTimeHappy(myDateTime) ? null : myDateTime

En el caso anterior no hay ninguna ruta de conversión entre null y DateTime. Tan pronto como lanzas uno de ellos a DateTime?, el compilador puede convertir el otro:

IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime

La línea de puño de código anterior funciona porque el compilador puede convertir DateTime a DateTime? a través de un operador de conversión implícita:

//In Nullable<T>
public static implicit operator T?(T value);

funciona La segunda línea porque null se puede asignar a DateTime? puesto que éste es un tipo de referencia.

La conversión implícita no está permitido por la instrucción de retorno. Si tenías

if (condition)
    return first_expression;
else
    return second_expression;

A continuación, sería comparar manzanas con manzanas. Y tendría ningún problema -. Como ha afirmado

En su caso, usted está asignado tanto espacio en la pila para un DateTime - que es un tipo de valor no anulable. Así que usted está haciendo una declaración que no tiene ningún sentido para el compilador. Si usted dice, voy a pasar a usted un A o una B, entonces el A y la necesidad B a ser la misma cosa. En su caso, la B nunca puede ser un A.

Creo que esto también es respondida aquí: tipos anulables y el operador ternario: ¿por qué? ' 10:? Null` prohibido

Espero que eso sea lo que sea necesario. =]

Lo que el compilador está diciendo es:

  

Si es IsDateTimeHappy(myDateTime) false, entonces tengo que devolver un valor de tipo DateTime igual a myDateTime. Si se trata de true, entonces necesito devolver un valor igual a null, pero no me ha dicho qué tipo debe ser!

Es por eso que la respuesta de la marca es la solución. Después de proporcionar un molde decirle al compilador qué tipo de valor será devuelto si la condición es true, se puede comprobar si los valores de retorno true y false se pueden convertir a (o son de) del mismo tipo.

Saludos Marcos! ; -)

En lugar de uso null default(DateTime?) y entonces ambos lados de la ternario tendrán tipos compatibles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top