Использование null-coalescing в качестве замены блока try catch - PullRequest
2 голосов
/ 27 декабря 2011

Почему я получаю недопустимое исключение приведения при попытке установить значение NULL, возвращаемое из базы данных внутри Comments, которое имеет тип Int32.

Я пытаюсь заменить это:

                try
                {
                    objStreamItem.Comments = (Int32)sqlReader["Comments"];
                    if (objStreamItem.Comments > 0) { 
                        listComments = Comment.GetAll(objStreamItem.Id);

                    }
                }
                catch (InvalidCastException)
                {
                    // Execute if "Comments" returns NULL
                    listComments = null;
                    objStreamItem.Comments = 0;
                }

С этим:

Comments = ((Int32?)sqlReader["Comments"]) ?? 0

Оба находятся в разных контекстах, но вы должны понять. Вместо того, чтобы использовать блок try catch, я пытаюсь решить эту проблему более элегантно.

Спасибо.

UPDATE

Он хранится в базе данных в виде целого числа, допускающего обнуление.

    public int? Comments
    {
        get;
        set;
    }

Я просто хочу поблагодарить всех, кто ответил или написал на этот вопрос, все было очень информативно. спасибо!

Ответы [ 4 ]

7 голосов
/ 27 декабря 2011

Ваш читатель SQL возвращает DBNull, когда значение равно нулю;Преобразование из DBNull в int? отсутствует, и оператор с нулевым слиянием не распознает DBNull.Value как нечто, требующее объединения.

РЕДАКТИРОВАТЬ 3

(Еще одна проблема с вашим исходным кодом: предполагается, что «Комментарии» вернули ноль, если «Комментарии» не ноль, но GetAll() выдает InvalidCastException.)

Как указывает hvd,вы можете использовать оператор as с обнуляемыми типами:

objStreamItem.Comments = sqlReader["Comments"] as int?;
listComments = (objStreamItem.Comments ?? 0) > 0 ? Comment.GetAll(objStreamItem.ID) : null;

Однако вы можете уберечься от всего этого, если просто определили Comment.GetAll(), чтобы возвращать пустой список или нулевую ссылку, когда идентификатор выперейти к нему нет комментариев.

2 голосов
/ 27 декабря 2011

Полагаю, здесь нужно использовать троичное выражение

objStreamItem.Comments = sqlReader["Comments"] is DBNull ? 0 : (Int32)sqlReader["Comments"] ;

Вы также можете сначала сохранить возвращаемое значение sqlReader["Comments"] в переменной, чтобы сократить выражение

var comments = sqlReader["Comments"];
objStreamItem.Comments = comments is DBNull ? 0 : (Int32)comments;
2 голосов
/ 27 декабря 2011

Оператор ?? проверяет null, но sqlReader["Comments"] никогда не будет null.Это будет либо Int32, либо DBNull.Вы можете разыграть null до Int32?, но вы не можете сделать это с DBNull.Value.Вместо этого вы можете использовать sqlReader["Comments"] as Int32?, который проверяет, можно ли преобразовать результат в Int32, а если нет, присваивает null.

1 голос
/ 27 декабря 2011

Этот оператор пытается выполнить приведение перед объединением значений. Вам нужно добавить скобки. Судя по приведенному выше примеру, это также выглядит как поле int, а не int?:

Comments = (Int32)(sqlReader["Comments"] ?? 0);
...