25 votes

Comment int + string devient string?

Je suis tombé sur une étrange façon de mettre en œuvre ToString() et je me demande comment cela fonctionne:

 public string tostr(int n) 
{
    string s = "";
    foreach (char c in n-- + "") {  //<------HOW IS THIS POSSIBLE ?
        s = s + c;
    }
    return s;
}
 

L'itérateur suppose-t-il la taille d'un char ?

19voto

user2946329 Points 10394

Il appelle l' String.Concat(object, object) méthode implicite, qui concatène la chaîne des représentations de deux spécifié objets:

string result = String.Concat("", n--);

L' String.Concat(object, object) méthode appelle alors String.Concat(string, string). Pour lire l' Concat's de la source et vérifier plus en profondeur, d'abord rendez-vous ici: Chaîne de caractères.cs code source en C# .NET et puis dans cette page à la recherche d' TextBox type String , puis cliquez sur l' String.cs lien dans les résultats pour aller à la Chaîne.cs code source en C# .NET page et cochez l' Concat méthode.

C'est la définition de la méthode:

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()); 
}

Comme vous le voyez c'appels public static String Concat(String str0, String str1) méthode enfin:

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;
}

Et c'est le sous-jacent IL, par Ildasm:

.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

15voto

Mateusz Points 5130

Expliquer cette "étape par étape":

 // 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
}
 

Donc, fondamentalement, si vous concaténez string avec int il appellera automatiquement la méthode int.ToString et joindra la chaîne ensemble.

10voto

Codor Points 1861

Le type de n-- est int , qui est converti en string en utilisant + pour le concaténer avec "" , qui est de type string . En outre, string implémente IEnumerable<char> , sur lequel l'itération réelle avec foreach a lieu.

6voto

InBetween Points 6162

Ce code est incompréhensible parce que ses le résultat de ce que je considère comme un terrible choix de conception dans la langue.

L' + opérateur n'existe pas vraiment en string. Si vous regardez la source de la référence ou de la page MSDN, la seule déclaré opérateurs pour l' string sont == et !=.

Ce qui se passe réellement est que le compilateur tire l'un de ses tours de magie, et convertit l' + de l'opérateur dans un appel à la méthode statique string.Concat.

Maintenant, si vous est arrivé de rencontrer foreach (char c in string.Concat(n--, "")) vous auriez probablement comprendre le code de beaucoup mieux, parce que l'intention est claire: je veux concaténer deux objets comme des chaînes de caractères et ensuite l'énumération de l' chars qui composent la chaîne résultante.

Quand vous lisez n-- + "" que l'intention est loin d'être claire, et son pire si vous avez n-- + s (s être string).

Le compilateur dans les deux cas, décide que vous voulez concaténer les arguments comme des chaînes de caractères et automatiquement les cartes de cet appel à l' string.Concat(object, object). Un de C#'s des locataires est que, à moins que l'intention du codeur est clair, d'agiter un drapeau rouge et de demander au programmeur de clarifier ses intentions. Dans ce cas particulier, le locataire est violé complètement.

À mon humble avis, tout ce qui n'est pas un string + string doit avoir été une erreur de compilation, mais que le train est passé le long il y a plusieurs années.

1voto

Fabulous Points 2010

Pour briser votre code de montrer pourquoi il arrive...

foreach(char c in n-- + "")

à l'aide de l' + de l'opérateur avec une chaîne de caractères comme l'un des opérandes vous permet de convertir le résultat d'une chaîne de caractères indépendamment de ce que les autres primitives de l'opérande a été, tant il avait de mise en œuvre de +. En agissant de la sorte, n participe à l' string.Concat méthode comme vous pouvez le voir sur la capture d'écran suivante des Autos fenêtre de débogage...

Autos window showing identifier values

J'ai appelé la méthode avec "34" comme vous pouvez le déduire. La boucle de l'identificateur est défini comme char c et passe par une chaîne. Cela fonctionne parce qu' string implémente IEnumerable<char> comme vous pouvez le voir sur la capture d'écran du résultat "d'Aller à la définition" de type chaîne de caractères:

Result of right clicking string type and going to definition

Alors à partir de ce point, il fonctionne de la même comme si vous étiez une itération à travers toute autre liste/tableau... ou, plus précisément, IEnumerable avec foreach et obtient chaque char. n moyenne de temps a été changé à l' n-- // 33 in my case. À ce stade, la valeur de n n'est pas sans conséquence puisque vous êtes d'une itération dans le résultat de l'expression n-- + "". Il peut aussi bien avoir été n++ et vous obtenez le même résultat.

La ligne s = s + c; devrait être assez explicite et juste au cas où il ne l'est pas, chaque char tirez-vous de la chaîne temporaire résultat d' n-- + "" est ajouté à votre vide (au début) string s = "";. Il en résulte une chaîne, car comme mentionné précédemment + avec une chaîne concernés seront le résultat dans une chaîne de caractères. Une fois que vous avez fait passer par tous les chars, il renvoie la représentation de chaîne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X