it-swarm-pt.tech

Atribuição condicional do operador com tipos <valor> anuláveis?

EmployeeNumber =
string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? null
    : Convert.ToInt32(employeeNumberTextBox.Text),

Muitas vezes me vejo querendo fazer coisas assim (EmployeeNumber é um Nullable<int> como uma propriedade em um objeto dbml LINQ-to-SQL em que a coluna permite valores NULL). Infelizmente, o compilador considera que "Não há conversão implícita entre 'nulo' e 'int'", mesmo que os dois tipos sejam válidos em uma operação de atribuição para um int nulo por conta própria.

O operador coalescente nulo não é uma opção, pelo que pude ver, devido à conversão em linha que precisa ocorrer na string .Text, se não for nula.

Tanto quanto sei, a única maneira de fazer isso é usar uma instrução if e/ou atribuí-la em duas etapas. Nesse caso em particular, acho isso muito frustrante, porque eu queria usar a sintaxe do inicializador de objetos e essa atribuição estaria no bloco de inicialização ...

Alguém conhece uma solução mais elegante?

57
Grank

O problema ocorre porque o operador condicional não analisa como o valor é usado (atribuído neste caso) para determinar o tipo da expressão - apenas os valores verdadeiro/falso. Nesse caso, você tem um nulo e um Int32, e o tipo não pode ser determinado (existem razões reais para não posso simplesmente assumir Anulável <Int32>).

Se você realmente deseja usá-lo dessa maneira, deve converter um dos valores para Nullable <Int32> você mesmo, para que o C # possa resolver o tipo:

EmployeeNumber =
    string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? (int?)null
    : Convert.ToInt32(employeeNumberTextBox.Text),

ou

EmployeeNumber =
    string.IsNullOrEmpty(employeeNumberTextBox.Text)
    ? null
    : (int?)Convert.ToInt32(employeeNumberTextBox.Text),
65
Alex Lyman

Eu acho que um método utilitário poderia ajudar a tornar isso mais limpo.

public static class Convert
{
    public static T? To<T>(string value, Converter<string, T> converter) where T: struct
    {
        return string.IsNullOrEmpty(value) ? null : (T?)converter(value);
    }
}

então

EmployeeNumber = Convert.To<int>(employeeNumberTextBox.Text, Int32.Parse);
8
NerdFury

Enquanto Alex fornece a resposta correta e proximal à sua pergunta, prefiro usar TryParse:

int value;
int? EmployeeNumber = int.TryParse(employeeNumberTextBox.Text, out value)
    ? (int?)value
    : null;

É mais seguro e cuida dos casos de entrada inválida, bem como do seu cenário de cadeia vazia. Caso contrário, se o usuário inserir algo como 1b, Será apresentada uma página de erro com a exceção não tratada causada em Convert.ToInt32(string).

6
user13493

Você pode converter a saída do Convert:

EmployeeNumber = string.IsNullOrEmpty(employeeNumberTextBox.Text)
   ? null
   : (int?)Convert.ToInt32(employeeNumberTextBox.Text)
3
Abe Heidebrecht
//Some operation to populate Posid.I am not interested in zero or null
int? Posid = SvcClient.GetHolidayCount(xDateFrom.Value.Date,xDateTo.Value.Date).Response;
var x1 = (Posid.HasValue && Posid.Value > 0) ? (int?)Posid.Value : null;

EDIT: Breve explicação acima, eu estava tentando obter o valor de Posid (se for nulo int e com valor maior que 0) em varibale X1. Eu tive que usar (int?) em Posid.Value para que o operador condicional não gere nenhum erro de compilação. Apenas um FYI GetHolidayCount é um método WCF que pode fornecer null ou qualquer número. espero que ajude

1
Sandeep