【问题标题】:How to cope with when exhaustive issue if i don't have nothing to return i case of else?如果在其他情况下我没有什么可退还的,如何处理详尽的问题?
【发布时间】:2020-11-21 22:37:34
【问题描述】:

我有一个逻辑上只能有 3 个值的代码。但是 when 赋值是在一个 Int 变量类型上。如果我没有 RecyclerView.ViewHolder 对象要返回,如果 when 表达式中没有任何“情况”不会发生(这种情况不可能),我该怎么办。 我可以用“丑陋”的解决方案来解决它,如果 'else' 则返回我在现有案例中返回的 RecyclerView.ViewHolder 之一,但我想知道是否有更优雅的方法来处理这种情况。 我有以下代码:

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    return when (viewType)
     {
         DataTypesEnum.COUNTRY_ITEM.ordinal -> CountryDataItem.onCreateViewHolder(parent)
         DataTypesEnum.LEAGUE_ITEM.ordinal -> LeagueDataItem.onCreateViewHolder(parent)
         DataTypesEnum.GAME_ITEM.ordinal ->  GameDataItem.onCreateViewHolder(parent)
     }
}

编译器说:

when'表达式必须是详尽的,添加必要的'else'分支

【问题讨论】:

    标签: android kotlin case-when


    【解决方案1】:

    在您的情况下,可以抛出InvalidArgumentException。永远不会发生未知的ViewHolder 类型可以达到这一点。如果发生这种情况,则说明出现了严重错误,您希望得到通知。

     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType)
         {
             DataTypesEnum.COUNTRY_ITEM.ordinal -> CountryDataItem.onCreateViewHolder(parent)
             DataTypesEnum.LEAGUE_ITEM.ordinal -> LeagueDataItem.onCreateViewHolder(parent)
             DataTypesEnum.GAME_ITEM.ordinal ->  GameDataItem.onCreateViewHolder(parent)
             else -> throw InvalidArgumentException("Invalid ViewHolder Type")
         }
    }
    

    如果您想避免该警告,您可以使用kotlin require operator 并以这种方式排除不允许的值。但是,如果任何不允许的值进入该函数,它也会抛出异常。

    【讨论】:

    • 我阅读了您发送的链接。但我不明白 require 如何为我服务以防止 else 或者我应该在 else “案例”中使用 require
    • @Eitanos30 require、check、error 是用于预检查的函数,在这种情况下是没有用的。
    【解决方案2】:

    [我]想知道是否有更优雅的方式来处理这种情况。

    如果您绝对确定viewType 索引将在正确的范围内,则可以从列表中获取enum。然后你只需要打开那个枚举。

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
      return when (DataTypesEnum.values()[viewType])
      {
        DataTypesEnum.COUNTRY_ITEM -> CountryDataItem.onCreateViewHolder(parent)
        DataTypesEnum.LEAGUE_ITEM -> LeagueDataItem.onCreateViewHolder(parent)
        DataTypesEnum.GAME_ITEM ->  GameDataItem.onCreateViewHolder(parent)
      }
    }
    

    我同意 J. Hegg 的 response 的观点,你应该小心!


    2020 年 11 月 23 日更新,提供更多背景信息:

    我只是很好奇 (DataTypesEnum.values()[viewType]) 行如何使所有 when return 语句详尽无遗并防止编译器抱怨详尽的问题?

    在您的初始示例中,您打开 Int 类型。

    when (viewType) {
      // ...
    }
    

    因此,为了让编译器对viewTypes 感到满意,您要么需要覆盖Int 的所有可能值,要么在when 块中包含else 语句。

    我的建议是在开启之前将Int 类型映射到对应的DataTypesEnum。这样,when 块只需要考虑到所有 DataTypesEnum 选项是详尽无遗的。

    DataTypesEnum.values() 按顺序返回所有DataTypesEnumArray<DataTypesEnum>,这与在您的解决方案中使用#ordinal values 非常相似。

    下一步是从数组中获取值,我使用index access operator[ ]

    DataTypesEnum.values()[viewType]
    // is the same as
    DataTypesEnum.values().get(viewType)
    

    这应该可以解决问题!

    如果您不确定viewType 是否在正确的范围内,您可能需要检查so you don't hit an IndexOutOfBoundsException 的值。

    希望能回答你的问题!

    【讨论】:

    • @Salvastore Testa,你能解释一下为什么你写的代码不会导致编译错误吗?我理解代码但不明白它为什么起作用?编译器不知道枚举只能得到3个值
    • @Eitanos30,我很乐意尝试!你希望编译器抱怨我写的哪一部分?
    • 我必须说我已经检查了你写的东西,它确实有效。但是,我只是很好奇 (DataTypesEnum.values()[viewType]) 行如何使所有 when return 语句详尽无遗并防止编译器抱怨详尽的问题?跨度>
    • 是的,我明白了,再次感谢!!!但我很好奇编译器(不是运行时)如何知道只有 3 个可能的值:DataTypesEnum.values()[viewType]?他实际上并没有检查有多少枚举值(只有 3 个)..
    • 编译器知道枚举类和密封类的所有可能情况。见这里:kotlinlang.org/docs/reference/control-flow.html#when-expression
    猜你喜欢
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多