Отображение ошибки безопасности Null после проверки на null

Я выполняю функцию (listOf(matchUid, first_name, gender, matchBio, age).any { it == null }), которая проверяет, является ли какая-либо из переданных переменных null:

private fun getMatchData(doc: DocumentSnapshot){
    val matchUid = if (isUser1) doc.getString("user2") else doc.getString("user1")
    val first_name = if (isUser1) doc.getString("user2name") else doc.getString("user1name")
    val gender = if (isUser1) doc.getString("user2gender") else doc.getString("gender")
    val matchBio = if (isUser1) doc.getString("user2bio") else doc.getString("user1bio")
    if ( listOf(matchUid, first_name, gender, matchBio, age).any { it == null } ) return goOffline()
    if (matchUid == null) return goOffline()
    if (!isUser1) Group = Group().apply {
        id = doc.id
        user1 = matchUid
        user2 = user.uid
        match = User(matchUid, first_name, gender, null, true)
    } 

Несмотря на то, что он проверяет это, first_name и gender подчеркнуты красным цветом компилятором из-за нулевой безопасности. matchUid не имеет красной линии, потому что я явно проверяю наличие нуля в строке ниже.

Почему компилятор все еще выдает нулевое предупреждение после того, как я его уже проверил?


person Zorgan    schedule 17.10.2019    source источник
comment
Я полагаю, потому что компилятор недостаточно умен.   -  person Boris the Spider    schedule 17.10.2019
comment
Я бы сказал, что компилятор не может знать, что вы делаете со списком или можете ли вы сопоставить элементы с чем-то другим. Чтобы сделать это, потребуется определенный анализ кода, который, вероятно, выходит за рамки возможностей большинства компиляторов. Даже вы, как человек, не сможете сказать, что на самом деле происходит, если вы не знаете, что именно делает listOf(...).   -  person Thomas    schedule 17.10.2019


Ответы (1)


Итак, проблема в том, что компилятор недостаточно умен, или... мы не предоставляем достаточно информации.

В вашем случае проблемный вызов, в котором вы гарантируете, что firstName и gender не равны нулю:

if (listOf(matchUid, firstName, gender, matchBio, age).any { it == null }) return goOffline()

Если вы измените его на простую цепочку нулей, она будет работать правильно:

if (matchUid == null || firstName == null || gender == null || matchBio == null || age == null) return goOffline()

Итак, почему это? Компилятор просто не знает, что listOf(vararg objects: Any?).any { it == null } означает, что ни один из этих объектов не является нулевым. Итак, что мы можем сделать?

Kotlin 1.3 дал нам прекрасную возможность написать contracts, которые являются подсказкой для компилятора, например, если f(x) возвращает true, значит x не равно нулю. Но, к сожалению, контракты не поддерживают аргумент varargs (или я не нашел способ сделать это).

Итак, в вашем случае вы можете заменить свой вызов цепочкой одиночной нулевой проверки.

person Cililing    schedule 17.10.2019