let decodedString = "www.mydomain.com%2Fkey=%E0%A4%85%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A4%AF"
if let unwrappedDecodedString = decodedString.removingPercentEncoding {
print(unwrappedDecodedString) // www.mydomain.com/key=अक्षय
}
在上面的示例中,GetPropertyValue2编译,但GetPropertyValue和GetPropertyValue3没有。 将字典或列表中的值作为引用返回有什么问题,而它对数组有效吗?
答案 0 :(得分:2)
我想将我的答案添加到“锅”中,也许这会让事情变得更加清晰。 那么,为什么列表和词典不起作用呢?好吧,如果你有一段这样的代码:
static string Test()
{
Dictionary<int, string> s = new Dictionary<int, string>();
return s[0];
}
这(在调试模式下)转换为此IL代码:
IL_0000: nop
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.Dictionary`2<int32, string>::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.0
IL_0009: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int32, string>::get_Item(!0)
IL_000e: stloc.1
IL_000f: br.s IL_0011
IL_0011: ldloc.1
IL_0012: ret
这反过来意味着你用一行代码(return s[0]
)做的事实上是一个三步过程:调用方法,将返回值存储在局部变量中,然后返回值存储在该局部变量中。并且,正如其他人提供的链接所指出的那样,通过引用返回局部变量是不可能的(除非局部变量是ref局部变量,但正如其他人所指出的那样,因为Diciotionary<TKey,TValue>
和{ {1}}没有按引用返回API,这也是不可能的。
现在,为什么它适用于阵列?如果你看一下如何更仔细地处理数组索引(即在IL代码级别),你可以看到没有方法调用数组索引。相反,一个特殊的操作码被添加到名为ldelem(或其中的一些变体)的代码中。像这样的代码:
List<T>
在IL中翻译成这个:
static string Test()
{
string[] s = new string[2];
return s[0];
}
当然这看起来和字典一样,但我认为关键的区别在于索引器在这里生成一个IL-native调用,而不是一个属性(即方法)调用。如果你查看MSDN here上所有可能的ldelem变体,你可以看到有一个叫做 ldelema 的变种,它可以直接将元素的地址加载到堆中。事实上,如果你写一段这样的代码:
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: newarr [mscorlib]System.String
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.0
IL_000a: ldelem.ref
IL_000b: stloc.1
IL_000c: br.s IL_000e
IL_000e: ldloc.1
IL_000f: ret
这转换为以下IL代码,利用直接引用加载ldelema操作码:
static ref string Test()
{
string[] s = new string[2];
return ref s[0];
}
所以基本上,数组索引器是不同的,并且通过本机IL调用,数组支持通过引用评估堆栈来加载元素。由于IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: newarr [mscorlib]System.String
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: ldc.i4.0
IL_000a: ldelema [mscorlib]System.String
IL_000f: stloc.1
IL_0010: br.s IL_0012
IL_0012: ldloc.1
IL_0013: ret
和其他集合将索引器实现为属性,这导致方法调用,因此只有在显式调用的方法指定ref返回时,它们才能执行此操作。