int + string如何成为字符串?

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)

  • 我一直认为`+`字符串运算符背后的"魔力"是一个糟糕的设计.运算符实际上并不存在,编译器会做一些魔术并调用`Concat`.我发现`1 + s`应该隐含地将一个数字转换为一个字符串,这是任何容易陷入的pifall,特别是新手程序员.`string.Concat(1,s)`应该是唯一的选项,任何不是`string + string`的东西应该是编译时错误. (2认同)

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)

所以基本上,如果您连接stringint它会自动调用int.ToString方法和联合起来的字符串.

  • 注意`n - `是一个后递减,所以`n`被转换为一个带有'n +""`的字符串,然后递减. (6认同)

Cod*_*dor 10

n--is 的类型,通过使用它来连接int转换为类型.此外,实现了实际迭代的实现.string+""stringstringIEnumerable<char>foreach


InB*_*een 6

这段代码看起来很难理解,因为它是我认为语言中可怕的设计选择的结果.

+运营商并没有真正存在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应该是编译时错误的东西,但那列火车很多年前就已经过了.

  • 回到过去的美好时光 - 电脑的"黄金时代" - 令人敬畏的意味着令人敬畏. (2认同)