C # Возвращаемое значение свойства, допускающего значение NULL

Возможный дубликат:
Введите результат с помощью тернарного оператора в C #

Я столкнулся с этим сценарием, и, похоже, нет естественного способа вернуть значение int, допускающее значение NULL. Приведенный ниже код дает ошибку компиляции, потому что тернарный оператор не любит null.

public int? userId
{
    get
    {
        int rv;
        return int.TryParse(userIdString, out rv) ? rv : null;
    }
}

Так что вам (или только мне) действительно нужно пройти весь путь и изложить все:

public int? userId
{
    get
    {
        int id;
        if(int.TryParse(userIdString, out id)){
           return id;
        }
        return null;
    }
}

РЕДАКТИРОВАТЬ: Есть ли более естественный способ создания экземпляра, допускающего значение NULL, чтобы заставить работать тернарный оператор?


person Haoest    schedule 15.09.2010    source источник
comment
Я делаю это, когда чувствую, что ответ указывает на мой вопрос. Но я часто задаю плохие и неоднозначные ответы.   -  person Haoest    schedule 15.09.2010


Ответы (3)


РЕДАКТИРОВАТЬ: я недостаточно внимательно прочитал вопрос; проблема не в том, что условный оператор не любит значения NULL, а в том, что ему нужно знать, каким должен быть общий тип выражения ... и этот тип должен быть типом либо левая сторона, или правая сторона. null сам по себе является выражением без типа, которое может быть преобразовано во многие типы; int - вполне допустимый тип, но это один из типов, в который null нельзя преобразовать. Вы можете явно сделать правую часть типа int? и получить неявное преобразование int в int? с левой стороны, или вы можете выполнить приведение с левой стороны, и получить неявное преобразование null в int?.

Мой ответ похож на ответ Джеймса, но вместо этого я использую нуль:

public int? userId 
{ 
    get 
    { 
        int rv; 
        return int.TryParse(userIdString, out rv) ? rv : (int?) null; 
    } 
}

Это подчеркивает, что это не пустая ссылка; это нулевое значение типа int?. В этот момент преобразование int rv очевидно.

Однако есть еще две альтернативы в том же духе:

return int.TryParse(userIdString, out rv) ? rv : new int?(); 

return int.TryParse(userIdString, out rv) ? rv : default(int?); 

Лично я считаю, что "приведенный нуль" - самая лучшая форма, но вы можете принять собственное решение.

Другой альтернативой может быть общий статический метод:

public static class Null
{
    public static T? For<T>() where T : struct
    {
        return default(T?);
    }
}

и писать:

return int.TryParse(userIdString, out rv) ? rv : Null.For<int>(); 

Не думаю, что мне это очень нравится, но предлагаю на ваш осмотр :)

person Jon Skeet    schedule 15.09.2010
comment
Мне здесь нравится более глубокий подход ... Однако вопрос: преобразование нуля в int? для компилятора или для разработчиков? - person Nathan Wheeler; 15.09.2010
comment
@ md5sum: Оба ... без него компилятор не будет знать, какой тип использовать для общего условного выражения. - person Jon Skeet; 16.09.2010
comment
@ md5sum, когда задано bool ? int : null, компилятор не поспешит сказать, что оба конвертируются в int?. Он совершит прыжок для одного из них и скажет, что int может быть int? или null может быть int?, но вам нужно, так сказать, внедрить предложение int? в мозг компилятора. - person Anthony Pegram; 16.09.2010

Вы возвращаете (не допускающее значения NULL) int или null в том же выражении. Чтобы это сработало, вам нужно будет явно вернуть int? в тернарном выражении.

person Bob    schedule 15.09.2010

person    schedule
comment
+1 за то, что набираю быстрее, чем я могу! :П - person Nathan Wheeler; 15.09.2010
comment
Но, видимо, кому-то не понравился этот ответ --- меня проиграли (но, похоже, он тебя тоже ударил) - person James Curran; 15.09.2010
comment
Да ... Я только что научился игнорировать троллей, проголосовавших против ... - person Nathan Wheeler; 15.09.2010
comment
Я проголосовал против обоих, потому что считаю, что другие ответы были лучше, и хотел бы, чтобы они были наверху, и для этого нужны голоса за / против. @ md5sum, просто потому, что вы получили отрицательный голос, это не значит, что ответ плохой. Это просто способ сдвинуть ответы вверх / вниз. - person Filip Ekberg; 15.09.2010
comment
@Filip: Но Энтони ошибается, а Боб, хотя и прав, просто повторяет то, что ОП уже знает, не помогая ему это исправить. - person James Curran; 15.09.2010
comment
@Filip, смотрите, как хотите, но я склонен думать, что отрицательные голоса должны быть зарезервированы для ответов, которые являются неправильными или технически правильными (значит, это сработает), непродуманным кодом. Однако мой был неправ. По крайней мере, в диагностической части! - person Anthony Pegram; 15.09.2010
comment
Просто предоставление кода редко помогает OP, в следующий раз он спросит, как делать то же самое. Некоторое поясняющее содержание всегда намного лучше, чем просто образец кода. А также ответ @ md5sum является дубликатом и должен быть удален, поэтому также отклонен. - person Filip Ekberg; 15.09.2010
comment
Каждый раз, когда я начинаю испытывать энтузиазм по поводу SO и пытаюсь помочь людям, приходит кто-то вроде @Filip и напоминает мне, чтобы я не тратил время здесь или, по крайней мере, не верил, что представитель SO имеет какое-то конкретное значение. - person Gabriel Magana; 15.09.2010
comment
@Anthony: На самом деле, я имел в виду вашу (int?) Нулевую часть, которая, как я подумал, была неправильной. Но после того, как Джон Скит порекомендовал то же самое, мне пришлось на самом деле попробовать это, чтобы доказать себе, что это сработает. - person James Curran; 15.09.2010
comment
Ну да, вы можете использовать любую сторону, но теперь вы узнали, что приведение null к int? допустимо. Вам просто нужно уйти от bool ? int : null, потому что компилятор автоматически не скажет, что int может быть int?, null может быть int?, хорошо, это выражение возвращает int?. Он совершит прыжок для одного из них, когда ему будет предоставлена ​​соответствующая информация, но не для обоих. - person Anthony Pegram; 16.09.2010