Условное назначение оператора с помощью типов Nullable <value>?

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

Я часто нахожу, что хочу делать что-то вроде этого (EmployeeNumber является Nullable<int>, поскольку он является свойством в объекте dbml LINQ to SQL, где столбец допускает значения NULL). К сожалению, компилятор считает, что "нет никакого неявного преобразования между" null "и" int ", хотя оба типа были бы действительны в операции присваивания с помощью NULL int.

Оператор Null coalescing не является опцией, насколько я могу видеть из-за встроенного преобразования, которое должно произойти в строке .Text, если оно не равно null.

Насколько я знаю, единственный способ сделать это - использовать оператор if и/или назначить его в два этапа. В этом конкретном случае я нахожу это очень расстраивающим, потому что я хотел использовать синтаксис инициализатора объекта, и это назначение было бы в блоке инициализации...

Кто-нибудь знает более элегантное решение?

Ответы

Ответ 1

Проблема возникает из-за того, что условный оператор не смотрит, как это значение используется (назначается в этом случае), чтобы определить тип выражения - только значения true/false. В этом случае у вас есть null и Int32, и тип не может быть определен (есть реальные причины, по которым он не может просто принять Nullable <Int32 > ).

Если вы действительно хотите использовать его таким образом, вы должны сделать одно из значений Nullable <Int32 > самостоятельно, поэтому С# может разрешить тип:

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

или

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

Ответ 2

Я думаю, что полезный метод может помочь сделать это чище.

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);
    }
}

затем

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

Ответ 3

Пока Алекс дает правильный и проксимальный ответ на ваш вопрос, я предпочитаю использовать TryParse:

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

Это безопаснее и заботится о случаях недействительного ввода, а также о пустом сценарии. В противном случае, если пользователь вводит что-то вроде 1b, им будет представлена ​​страница с ошибкой с необработанным исключением, вызванным в Convert.ToInt32(string).

Ответ 4

Вы можете сделать вывод Convert:

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

Ответ 5

//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: Краткое объяснение выше, я пытался получить значение Posid (если его nonnull int и имеет значение больше 0) в varibale X1. Мне пришлось использовать (int?) на Posid.Value, чтобы оператор условного выражения не выдавал ошибку компиляции. Просто FYI GetHolidayCount - это метод WCF, который может дать null или любое число. Надеюсь, что поможет