11

Estoy tratando de utilizar el operador condicional, pero estoy quedarse atascado en el tipo que piensa que el resultado debería ser.resultado Tipo con el operador condicional en C#

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 puede se determinará porque no hay una conversión implícita entre '< null>' y 'System.DateTime'

Estoy confundido porque el parámetro es un tipo que admite nulos (DateTime?). ¿Por qué necesita convertirse en absoluto? Si es nulo, úsalo, si es una fecha y luego usa eso.

que estaba bajo la impresión de que:

condition ? first_expression : second_expression; 

fue el 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:.?. 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 valor asignado de datos que no se pueden hacer anulable.)

+0

posible duplicado de [Asignación de operador condicional con Nullable tipos?] (Http://stackoverflow.com/questions/75746/conditional-operator-assignment-with-nullablevalue-types) – nawfal

+0

posible duplicado de [tipos anulables y el operador ternario: ¿por qué es \ '? 10: null \ 'prohibited?] (Http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden) –

Respuesta

22

El compilador no infiere 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 elenco debería hacer el truco:

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

Ahora el compilador no tendrá problemas.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 una good answer que también es relevante aquí y entra en más detalles acerca de cómo el compilador determina los tipos .

+0

También menos detallada solución de declarar myDateTime como 'DateTime?' para comenzar: 'DateTime? myDateTime = DateTime.Now; ' –

1

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

if (condition) 
    return first_expression; 
else 
    return second_expression; 

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

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

2

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 compilador no puede saber cuál es el tipo de resultado.

IsDateTimeHappy(myDateTime) ? null : myDateTime 

En el caso anterior no hay camino 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); 

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

0

Lo que el compilador está diciendo es:

If IsDateTimeHappy(myDateTime) is false , then I need to return a value of type DateTime equal to myDateTime . If it is true , then I need to return a value equal to null , but you haven't told me what type it should be!

Es por eso que la respuesta de la marca es la solución. Después de proporcionar un molde que indica al compilador 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! ;-)

0

En lugar de null use default(DateTime?) y luego ambos lados del ternario tendrán tipos compatibles.

Cuestiones relacionadas