为什么在这个示例中,Swift通用约束似乎工作不一致?

我试图用Swift编写一些通用函数,并将版本限制为可选,但是我遇到的行为令我感到惊讶。

考虑以下代码(在操场上测试):

public protocol OptionalType {}
extension Optional: OptionalType {}

func asOptional<T>(_ t: T) -> T? { return t }
func asOptional<T>(_ t: T) -> T where T: OptionalType { return t }

class C {}

let c = C()
print(type(of: c))   //  #1 - C
print(type(of: asOptional(c)))   //  #2 - Optional<C>

let optc: C? = C()
print(type(of: optc))   //  #3 - Optional<C>
print(type(of: asOptional(optc)))   //  #4 - Optional<C>

func foo<T>(_ t: T) {
    print(type(of: t))   //  #5 - Optional<C>
    print(type(of: t) == type(of: optc))   //  #6 - true
    print(type(of: asOptional(t)))   //  #7 - Optional<Optional<C>> -- why?
}
foo(optc)

为什么#4和#7打印相同?在我看来,#7处的asOptional()调用应调用受约束的版本,就像#4处的调用一样(毕竟,toptc的类型与在上一行中选中)。为什么不?

pizi530 回答:为什么在这个示例中,Swift通用约束似乎工作不一致?

使用当时可用的类型信息在 compile 时完成两次asOptional()重载之间的解析。

print的输出向您显示运行时类型。

对于#4,optc的类型在编译时已知为Optional<C>,它符合OptionalType,因此编译器选择asOptional()的第二次重载

对于#7,t的类型仅 已知为某种类型 T,因此编译器必须选择asOptional()的第一次重载,如果t具有可选类型,则会在运行时导致双倍可选结果。

HTH

,

在第一种情况下,

int a = 50;

string result = string.Join(",",BitConverter.GetBytes(a).Reverse().Select(b => "0x" + b.ToString("X2")));

Console.WriteLine(result);

由于print(type(of: asOptional(optc))) // #4 - Optional<C> optc类型,所以调用了Optional方法,该方法返回非可选值。因此结果是单个可选

在第二种情况下,

func asOptional<T>(_ t: T) -> T where T: OptionalType

由于func foo<T>(_ t: T) { //.... print(type(of: asOptional(t))) // #7 - Optional<Optional<C>> -- why? } 非可选类型,因此将调用t方法,该方法返回可选值。这就是将func asOptional<T>(_ t: T) -> T?包裹在另一个t中,从而给出 double可选值的原因。

本文链接:https://www.f2er.com/3160866.html

大家都在问