Escriba el resultado con el operador condicional en C #

Estoy tratando de usar el operador condicional, pero me estoy colgando del tipo que cree que debería ser el resultado.

A continuación se muestra un ejemplo de que he logrado 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 indicada arriba, aparece el siguiente error de comstackción:

El 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 convertirse en absoluto? Si es nulo, úsalo, si es una fecha y luego usa eso.

Tenía la impresión de que:

 condition ? first_expression : second_expression; 

era lo mismo que:

 if (condition) first_expression; else second_expression; 

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

(NOTA: Sé que si hago de “myDateTime” un DateTime con nulos, funcionará. ¿Pero por qué lo necesita?

Como dije anteriormente, este es un ejemplo artificial. En mi ejemplo real “myDateTime” es un valor mapeado de datos que no se puede convertir en nulo.)

El comstackdor no infiere el tipo de resultado del operador condicional del uso del resultado, sino de los tipos de sus argumentos. El comstackdor falla cuando ve esta expresión porque no puede deducir el tipo del resultado:

 IsDateTimeHappy(myDateTime) ? null : myDateTime; 

Como null y DateTime no son compatibles, debe decirle al comstackdor cuál debe ser el tipo. Un elenco debería hacer el truco:

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

Ahora el comstackdor no tendrá problemas. También puede escribir lo anterior en una línea si lo prefiere (pero probablemente no haga esto):

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

Eric Lippert tiene una buena respuesta que también es relevante aquí y entra en más detalles sobre cómo el comstackdor determina los tipos.

La razón es que el operador ternario espera que ambos operandos sean del mismo tipo. El operador completo se resuelve ANTES de que se le asigne un resultado (en este caso pasado a una función), por lo que el comstackdor no puede saber cuál es el tipo de resultado.

 IsDateTimeHappy(myDateTime) ? null : myDateTime 

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

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

La primera línea de código anterior funciona porque el comstackdor puede convertir DateTime a DateTime? a través de un operador de conversión implícito:

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

La segunda línea funciona porque null se puede asignar a DateTime? ya que este último es un tipo de referencia.

La statement implícita no permite la conversión implícita. Si tuvieras

 if (condition) return first_expression; else return second_expression; 

Entonces estarías comparando manzanas con manzanas. Y no tendrías problemas, como dijiste.

En su caso, se le asigna tanto espacio en la stack para DateTime, que es un tipo de valor que no admite nulos. Entonces estás haciendo una statement que no tiene ningún sentido para el comstackdor. Si dices, voy a pasar una A o una B , entonces la A y la B deben ser lo mismo. En tu caso, el B nunca puede ser un A

Creo que esto también se responde aquí: tipos anulables y el operador ternario: ¿por qué es `? 10: nulo` prohibido?

Espero que sea lo que necesitabas. =]

Lo que el comstackdor está diciendo es:

Si IsDateTimeHappy(myDateTime) es false , entonces debo devolver un valor de tipo DateTime igual a myDateTime . Si es true , entonces necesito devolver un valor igual a null , ¡pero no me has dicho qué tipo debería ser!

Es por eso que la respuesta de Marcos es la solución. Después de proporcionar un molde que le dice al comstackdor qué tipo de valor se devolverá si la condición es true , puede verificar si los valores de retorno true y false se pueden convertir (o son) del mismo tipo.

¡Salud, Mark! 😉

En lugar del null default(DateTime?) uso null default(DateTime?) Y luego ambos lados del ternario tendrán tipos compatibles.