Nab*_*ben 28 .net c# obfuscation
我遇到了一种奇怪的实现方式ToString(),我想知道它是如何工作的:
public string tostr(int n)
{
string s = "";
foreach (char c in n-- + "") { //<------HOW IS THIS POSSIBLE ?
s = s + c;
}
return s;
}
Run Code Online (Sandbox Code Playgroud)
迭代器是否假定大小为char?
Sal*_*ari 21
它String.Concat(object, object)隐式调用该方法,它连接两个指定对象的字符串表示:
string result = String.Concat("", n--);
Run Code Online (Sandbox Code Playgroud)
String.Concat(object, object)然后该方法调用String.Concat(string, string).要阅读它Concat的源代码并进行深入检查,请首先转到此处:C#.NET中的String.cs源代码,然后在搜索TextBox类型的该页面中String,然后单击String.cs结果中的链接转到String.cs C#.NET页面中的源代码并检查Concat方法.
这是方法定义:
public static String Concat(Object arg0, Object arg1)
{
Contract.Ensures(Contract.Result<string>() != null);
Contract.EndContractBlock();
if (arg0 == null)
{
arg0 = String.Empty;
}
if (arg1==null)
{
arg1 = String.Empty;
}
return Concat(arg0.ToString(), arg1.ToString());
}
Run Code Online (Sandbox Code Playgroud)
正如你public static String Concat(String str0, String str1)最后看到这个调用方法:
public static String Concat(String str0, String str1)
{
Contract.Ensures(Contract.Result<string>() != null);
Contract.Ensures(Contract.Result<string>().Length ==
(str0 == null ? 0 : str0.Length) +
(str1 == null ? 0 : str1.Length));
Contract.EndContractBlock();
if (IsNullOrEmpty(str0)) {
if (IsNullOrEmpty(str1)) {
return String.Empty;
}
return str1;
}
if (IsNullOrEmpty(str1)) {
return str0;
}
int str0Length = str0.Length;
String result = FastAllocateString(str0Length + str1.Length);
FillStringChecked(result, 0, str0);
FillStringChecked(result, str0Length, str1);
return result;
}
Run Code Online (Sandbox Code Playgroud)
这是Ildasm的潜在IL :
.method public hidebysig instance string
tostr(int32 n) cil managed
{
// Code size 74 (0x4a)
.maxstack 3
.locals init ([0] string s,
[1] string V_1,
[2] int32 V_2,
[3] char c,
[4] string V_4)
IL_0000: nop
IL_0001: ldstr ""
IL_0006: stloc.0
IL_0007: nop
IL_0008: ldarg.1
IL_0009: dup
IL_000a: ldc.i4.1
IL_000b: sub
IL_000c: starg.s n
IL_000e: box [mscorlib]System.Int32
IL_0013: call string [mscorlib]System.String::Concat(object)
IL_0018: stloc.1
IL_0019: ldc.i4.0
IL_001a: stloc.2
IL_001b: br.s IL_0039
IL_001d: ldloc.1
IL_001e: ldloc.2
IL_001f: callvirt instance char [mscorlib]System.String::get_Chars(int32)
IL_0024: stloc.3
IL_0025: nop
IL_0026: ldloc.0
IL_0027: ldloca.s c
IL_0029: call instance string [mscorlib]System.Char::ToString()
IL_002e: call string [mscorlib]System.String::Concat(string,
string)
IL_0033: stloc.0
IL_0034: nop
IL_0035: ldloc.2
IL_0036: ldc.i4.1
IL_0037: add
IL_0038: stloc.2
IL_0039: ldloc.2
IL_003a: ldloc.1
IL_003b: callvirt instance int32 [mscorlib]System.String::get_Length()
IL_0040: blt.s IL_001d
IL_0042: ldloc.0
IL_0043: stloc.s V_4
IL_0045: br.s IL_0047
IL_0047: ldloc.s V_4
IL_0049: ret
}// end of method tostr
Run Code Online (Sandbox Code Playgroud)
Mat*_*usz 15
解释这个"一步一步":
// assume the input is 1337
public string tostr(int n) {
//line below is creating a placeholder for the result string
string s = "";
// below line we can split into 2 lines to explain in more detail:
// foreach (char c in n-- + "") {
// then value of n is concatenated with an empty string :
// string numberString = n-- + ""; // numberString is "1337";
// and after this line value of n will be 1336
// which then is iterated though :
// foreach(char c in numberString) { // meaning foreach(char c in "1337")
foreach (char c in n-- + "") { //<------HOW IS THIS POSSIBLE ?
s = s + c; // here each sign of the numberString is added into the placeholder
}
return s; // return filled placeholder
}
Run Code Online (Sandbox Code Playgroud)
所以基本上,如果您连接string与int它会自动调用int.ToString方法和联合起来的字符串.
这段代码看起来很难理解,因为它是我认为语言中可怕的设计选择的结果.
该+运营商并没有真正存在string.如果查看引用源或MSDN页面,那么唯一声明的运算符string是==和!=.
真正发生的是编译器提取其中一个神奇的技巧,并将+运算符转换为对静态方法的调用string.Concat.
现在如果碰巧遇到foreach (char c in string.Concat(n--, ""))你可能会更好地理解代码,因为意图很清楚:我想将两个对象连接成字符串,然后枚举char构成结果字符串的s.
当你读到n-- + ""这个意图远非明确时,如果你碰巧有n-- + s(sa string),那就更糟了.
两种情况下的编译器都决定您要将参数连接为字符串并自动将此调用映射到string.Concat(object, object).C#的一个租户是,除非编码器的意图明确,否则挥动红旗并要求编码人员澄清他的意图.在这种特殊情况下,该租户完全受到侵犯.
恕我直言,任何不是一个string + string应该是编译时错误的东西,但那列火车很多年前就已经过了.
| 归档时间: |
|
| 查看次数: |
3082 次 |
| 最近记录: |