二元运算符“+”不能应用于 'String' 和 'String?' 类型的操作数

Binary operator '+' cannot be applied to operands of type 'String' and 'String?'

编程新手,不太明白这是怎么回事,欢迎任何建议。

func exercise() {
    let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

    var char0 = alphabet.randomElement()
    var char1 = alphabet.randomElement()
    var char2 = alphabet.randomElement()
    var char3 = alphabet.randomElement()
    var char4 = alphabet.randomElement()
    var char5 = alphabet.randomElement()

    print(char0 + char1 + char2 + char3 + char4 + char5)
}

使用 ?? 为变量赋予默认值运算符在零的情况下。它会改变字符串的变量类型吗?到字符串

func exercise() {

    let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

    var char0 = alphabet.randomElement() ?? ""
    var char1 = alphabet.randomElement() ?? ""
    var char2 = alphabet.randomElement() ?? ""
    var char3 = alphabet.randomElement() ?? ""
    var char4 = alphabet.randomElement() ?? ""
    var char5 = alphabet.randomElement() ?? ""

    print(char0 + char1 + char2 + char3 + char4 + char5)
} 

错误消息中要理解的重要部分是String和String? (可选)被编译器认为是 2 种不同的类型。

在某些情况下,编译器可以进行(隐式)转换,因此类型相同但不在这里,因为它不能转换 nil 并且 + 运算符仅适用于相同的两个 variables/literal 值类型。

考虑这个案例

var char0 = alphabet.randomElement()
var char1 = alphabet.randomElement() ?? ""

如果我们现在 print("0: \(char0) 1: \(char1)") 两个变量的结果完全不同

0: Optional("p") 1: d

如果我们使用 print("0: \(type(of: char0)) 1: \(type(of: char1))")

检查它们的类型,我们也会看到

0: Optional<String> 1: String

其他人已经解释了为什么你的代码会报错。 (String.randomElement() returns 一个 Optional<String>,这与字符串不同,你不能使用 + 来连接 Optionals。)

还有一点:您的代码冗长且重复。在计算机科学中有一个原则,“DRY”。它代表“不要重复自己”。任何时候你一遍又一遍地使用相同的代码(可能有细微的变化),这就是“代码味道”,也是一个改进的机会。

您可以像这样不重复地重写您的代码:

func exercise() {
    let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

   var result = ""
   for _ in 1...6 {
     result.append(alphabet.randomElement() ?? "")
   }
   print(result)
}

在那个版本中,表达式alphabet.randomElement()只出现了一次。你不重复自己。它还使用 ??“nil 合并运算符”将可能为 nil 的结果转换为空白字符串。


另一种处理它的方法是定义 += 运算符的重写,使您可以将字符串可选值附加到字符串:

public func +=(left: inout String, right: Optional<String>) {
    left = left + (right ?? "")
}

那么你的函数就变成了:

func exercise() {
    let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
   var result = ""
   for _ in 1...6 {
    result += alphabet.randomElement()
   }
   print(result)
}

另一种方法是打乱源数组,获取前 6 个元素,然后将它们重新组合成一个字符串:

func exercise() {
    let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
    
    let result = alphabet
        .shuffled()[1...6]
        .joined()
    print(result)
}