Pergunta

Estou tentando usar o operador condicional, mas eu estou ficando pendurado sobre o tipo que pensa que o resultado deve ser.

Abaixo está um exemplo que eu tenho inventado para mostrar o problema que eu estou tendo:

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  ---------------+

Na linha indicada acima, recebo o seguinte erro de compilação:

Tipo de expressão condicional não pode ser determinado porque não há nenhuma conversão implícita entre '< null >' e 'Sistema.DateTime'

Estou confuso porque o parâmetro é um tipo anulável (DateTime?).O que é necessário para converter?Se for null, então o uso que, se é uma data de tempo, então use-o.

Eu estava sob a impressão de que:

condition ? first_expression : second_expression;

foi o mesmo que:

if (condition)
   first_expression;
else
   second_expression;

Claramente, este não é o caso.O que é o raciocínio por trás disso?

(NOTA:Eu sei que se eu fizer "myDateTime" um nullable DateTime, então ele vai funcionar.Mas por que ele precisa?

Como eu disse anteriormente, este é um exemplo imaginário.No meu exemplo real "myDateTime" é um dos dados mapeados valor que não pode ser feito anulável.)

Foi útil?

Solução

O compilador não infere o tipo de resultado do operador condicional do uso do resultado, mas dos tipos de seus argumentos. O compilador falha quando vê essa expressão porque não pode deduzir o tipo do resultado:

IsDateTimeHappy(myDateTime) ? null : myDateTime;

Desde null e DateTime Não são compatíveis, você precisa dizer ao compilador qual deve ser o tipo. Um elenco deve fazer o truque:

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

Agora o compilador não terá problemas. Você também pode escrever o acima em uma linha, se preferir (mas eu provavelmente não faria isso):

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

Eric Lippert tem um boa resposta Isso também é relevante aqui e entra em mais detalhes sobre como o compilador determina os tipos.

Outras dicas

O motivo é que o operador ternário espera que ambos os operandos sejam do mesmo tipo. Todo o operador é elaborado antes de ser atribuído a um resultado (neste caso passado para uma função), para que o compilador não possa saber qual é o tipo de resultado.

IsDateTimeHappy(myDateTime) ? null : myDateTime

No caso acima, não há caminho de conversão entre null e DateTime. Assim que você lança um deles para DateTime?, o compilador pode converter o outro:

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

A linha de código do punho acima funciona porque o compilador pode converter DateTime para DateTime? através de um operador de conversão implícito:

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

A segunda linha funciona porque null pode ser atribuído a DateTime? Como o último é um tipo de referência.

A conversão implícita não é permitida pela declaração de devolução. Se você tinha

if (condition)
    return first_expression;
else
    return second_expression;

Então você estaria comparando maçãs com maçãs. E você não teria problemas - como afirmou.

No seu caso, você é alocado muito espaço na pilha para um tempo de dados - que é um tipo de valor não indicado. Então, você está fazendo uma declaração que não faz nenhum sentido para o compilador. Se você disser, eu vou passar por você um A ou a B, então o A e a B Precisa ser a mesma coisa. No seu caso, o B nunca pode ser um A.

Eu acho que isso também é respondida aqui:Tipos anuláveis e o operador ternário:por que é `?10 :null` proibido?

Espero que o que você precisava.=]

O que o compilador está dizendo é:

Se IsDateTimeHappy(myDateTime) é false, então eu preciso retornar um valor do tipo DateTime igual a myDateTime. Se for true, então eu preciso retornar um valor igual a null, mas você não me disse que tipo deveria ser!

É por isso que a resposta de Mark é a solução. Depois de fornecer um elenco dizendo ao compilador que tipo de valor será retornado se a condição for true, pode verificar se o true e false Os valores de retorno podem ser convertidos para (ou são do mesmo tipo.

Saúde Mark! ;-)

Ao invés de null usar default(DateTime?) E então os dois lados do ternário terão tipos compatíveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top