Question

Comparer

String.Format("Hello {0}", "World");

avec

"Hello {0}".Format("World");

Pourquoi les concepteurs .Net ont-ils choisi une méthode statique plutôt qu’une méthode d’instance ?Qu'en penses-tu?

Était-ce utile?

La solution

Je ne connais pas vraiment la réponse, mais je soupçonne que cela a quelque chose à voir avec l'appel direct de méthodes sur des littéraux de chaîne.

Si je me souviens bien (je ne l'ai pas réellement vérifié car je n'ai pas d'ancien IDE à portée de main), les premières versions de l'IDE C# avaient du mal à détecter les appels de méthode contre les littéraux de chaîne dans IntelliSense, ce qui a un impact important sur la découvrabilité. de l'API.Si tel était le cas, taper ce qui suit ne vous aiderait pas :

"{0}".Format(12);

Si tu étais obligé de taper

new String("{0}").Format(12);

Il serait clair qu’il n’y avait aucun avantage à faire de la méthode Format une méthode d’instance plutôt qu’une méthode statique.

Les bibliothèques .NET ont été conçues par un grand nombre des mêmes personnes qui nous ont donné MFC, et la classe String en particulier présente une forte ressemblance avec la classe CString dans MFC.MFC dispose d'une méthode Format d'instance (qui utilise des codes de formatage de style printf plutôt que le style d'accolade de .NET) qui est pénible car il n'existe pas de littéral CString.Donc, dans une base de code MFC sur laquelle j'ai travaillé, je vois beaucoup de ceci :

CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);

ce qui est douloureux.(Je ne dis pas que le code ci-dessus est un excellent moyen de faire les choses même dans MFC, mais cela semble être la façon dont la plupart des développeurs du projet ont appris à utiliser CString :: Format).Fort de cet héritage, je peux imaginer que les concepteurs d'API essayaient à nouveau d'éviter ce genre de situation.

Autres conseils

Parce que la méthode Format n'a rien à voir avec la valeur actuelle d'une chaîne.

C'est vrai pour tous méthodes de chaîne car les chaînes .NET sont immuables.

S'il n'était pas statique, vous auriez besoin d'une chaîne pour commencer.

Cela fait:la chaîne de format.

Je pense que ce n'est qu'un autre exemple des nombreux défauts de conception de la plate-forme .NET (et je ne parle pas de cela comme d'une flamme ;Je trouve toujours le framework .NET supérieur à la plupart des autres frameworks).

Eh bien, je suppose que vous devez être assez particulier à ce sujet, mais comme les gens le disent, il est plus logique que String.Format soit statique en raison de la sémantique implicite.Considérer:

"Hello {0}".Format("World"); // this makes it sound like Format *modifies* 
                             // the string, which is not possible as 
                             // strings are immutable.

string[] parts = "Hello World".Split(' ');    // this however sounds right, 
                                             // because it implies that you 
                                             // split an existing string into 
                                             // two *new* strings.

La première chose que j'ai faite lors de la mise à niveau vers VS2008 et C#3, a été de faire ceci

public static string F( this string format, params object[] args )
{
    return String.Format(format, args);
}

Je peux donc maintenant changer mon code de

String.Format("Hello {0}", Name);

à

"Hello {0}".F(Name);

ce que je préférais à l'époque.De nos jours (2014), cela ne me dérange pas car c'est juste un autre problème de continuer à rajouter cela à chaque projet aléatoire que je crée ou à créer un lien dans une bibliothèque de sacs d'utilitaires.

Quant à savoir pourquoi les concepteurs .NET l'ont choisi ?Qui sait.Cela semble entièrement subjectif.Mon argent est soit sur

  • Copier Java
  • Le gars qui l’écrivait à l’époque l’aimait subjectivement plus.

Il n'y a pas vraiment d'autres raisons valables que je puisse trouver

Je pense que c'est parce que Format ne prend pas une chaîne en soi, mais une "chaîne de format".La plupart des chaînes sont égales à des éléments tels que "Bob Smith" ou "1010 Main St" ou autre et non à "Bonjour {0}". En général, vous n'insérez ces chaînes de format que lorsque vous essayez d'utiliser un modèle pour en créer un autre. string, comme une méthode d'usine, et se prête donc à une méthode statique.

Je pense que c'est parce que c'est une méthode de création (je ne sais pas s'il existe un meilleur nom).Tout ce qu'il fait, c'est prendre ce que vous lui donnez et renvoyer un seul objet chaîne.Il n'opère pas sur un objet existant.S'il n'était pas statique, vous auriez besoin d'une chaîne pour commencer.

Parce que la méthode Format n'a rien à voir avec la valeur actuelle d'une chaîne.La valeur de la chaîne n'est pas utilisée.Il prend une chaîne et en renvoie une.

Peut-être que les concepteurs .NET l'ont fait de cette façon parce que JAVA l'a fait de cette façon...

Embrassez et prolongez.:)

Voir: http://discuss.techinterview.org/default.asp?joel.3.349728.40

Les chaînes .NET sont immuables
Par conséquent, avoir une méthode d’instance n’a absolument aucun sens.

Selon cette logique, la classe de chaînes ne devrait avoir aucune méthode d'instance renvoyant des copies modifiées de l'objet, mais elle en a beaucoup (Trim, ToUpper, etc.).De plus, de nombreux autres objets du framework le font également.

Je suis d'accord que s'ils en faisaient une méthode d'instance, Format Il semble que ce serait un mauvais nom, mais cela ne signifie pas que la fonctionnalité ne devrait pas être une méthode d'instance.

Pourquoi pas ça ?C'est cohérent avec le reste de le framework .NET

"Hello {0}".ToString("Orion");

Les méthodes d'instance sont utiles lorsque vous disposez d'un objet qui conserve un certain état ;le processus de formatage d'une chaîne n'affecte pas la chaîne sur laquelle vous opérez (lire :ne modifie pas son état), il crée une nouvelle chaîne.

Avec les méthodes d'extension, vous pouvez désormais avoir le gâteau et le manger aussi (c'est-à-direvous pouvez utiliser cette dernière syntaxe si elle vous aide à mieux dormir la nuit).

Je pense qu'il semble préférable en général d'utiliser String.Format, mais je pourrais voir l'intérêt de vouloir avoir une fonction non statique lorsque vous avez déjà une chaîne stockée dans une variable que vous souhaitez "formater".

En passant, toutes les fonctions de la classe string n'agissent pas sur la chaîne, mais renvoient un nouvel objet chaîne, car les chaînes sont immuables.

@Jared :

Les méthodes statiques non surchargées et non héritées (comme Class.b(a,c)) qui prennent une instance comme première variable sont sémantiquement équivalentes à un appel de méthode (comme a.b(c))

Non, ils ne le sont pas.

(En supposant qu'il compile sur le même CIL, ce qu'il devrait être.)

C'est votre erreur.Le CIL produit est différent.La différence est que les méthodes membres ne peuvent pas être invoquées sur null valeurs afin que le CIL insère une vérification par rapport à null valeurs.Cela n'est évidemment pas fait dans la variante statique.

Cependant, String.Format fait pas permettre null valeurs, les développeurs ont donc dû insérer un chèque manuellement.De ce point de vue, la variante de la méthode des membres serait techniquement supérieure.

Ceci afin d'éviter toute confusion avec .ToString() méthodes.

Par exemple:

double test = 1.54d;

//string.Format pattern
string.Format("This is a test: {0:F1}", test );

//ToString pattern
"This is a test: " + test.ToString("F1");

Si Format était une méthode d'instance sur une chaîne, cela pourrait prêter à confusion, car les modèles sont différents.

String.Format() est une méthode utilitaire permettant de transformer plusieurs objets en une chaîne formatée.

Une méthode d'instance sur une chaîne fait quelque chose à cette chaîne.

Bien sûr, vous pourriez faire :

public static string FormatInsert( this string input, params object[] args) {
    return string.Format( input, args );
}

"Hello {0}, I have {1} things.".FormatInsert( "world", 3);

Je ne sais pas pourquoi ils ont fait ça, mais ça n'a plus vraiment d'importance :

public static class StringExtension
{
    public static string FormatWith(this string format, params object[] args)
    {
        return String.Format(format, args);
    }
}

public class SomeClass
{
    public string SomeMethod(string name)
    {
        return "Hello, {0}".FormatWith(name);
    }
}

Cela coule beaucoup plus facilement, à mon humble avis.

L’un des principaux objectifs de conception du C# était de rendre la transition du C/C++ vers ce langage aussi simple que possible.L'utilisation de la syntaxe par points sur une chaîne littérale ressemblerait à très étrange pour quelqu'un avec seulement une expérience en C/C++, et le formatage des chaînes est quelque chose qu'un développeur fera probablement dès le premier jour avec le langage.Je crois donc qu'ils l'ont rendu statique pour le rapprocher d'un territoire familier.

Une autre raison pour String.Format est la similitude avec la fonction printf de C.Il était censé permettre aux développeurs C de changer plus facilement de langue.

Je ne vois rien de mal à ce que ce soit statique.

La sémantique de la méthode statique me semble beaucoup plus logique.C'est peut-être parce que c'est un primitif.Là où les primitives sont souvent utilisées, vous souhaitez rendre le code utilitaire permettant de travailler avec elles aussi léger que possible.De plus, je pense que la sémantique est bien meilleure avec Chaîne.Format sur "MaChaîne BLAH BLAH {0}".Format ...

Les méthodes statiques non surchargées et non héritées (comme Class.b(a,c)) qui prennent une instance comme première variable sont sémantiquement équivalentes à un appel de méthode (comme a.b(c)), de sorte que l'équipe de la plateforme a créé un arbitraire, choix esthétique.(En supposant qu'il compile sur le même CIL, ce qui devrait être le cas.) La seule façon de savoir serait de leur demander pourquoi.

Peut-être qu'ils l'ont fait pour garder les deux cordes proches l'une de l'autre lexigraphiquement, c'est-à-dire

String.Format("Foo {0}", "Bar");

au lieu de

"Foo {0}".Format("bar");

Vous voulez savoir à quoi les index sont mappés ;peut-être pensaient-ils que la partie ".Format" ajoutait simplement du bruit au milieu.

Fait intéressant, la méthode ToString (au moins pour les nombres) est à l'opposé :number.ToString("000") avec la chaîne de format sur le côté droit.

Je ne l'ai pas encore essayé mais vous pouvez créer une méthode d'extension pour ce que vous voulez.Je ne le ferais pas, mais je pense que cela fonctionnerait.

Aussi je trouve String.Format() plus conforme à d'autres méthodes statiques structurées telles que Int32.Parse(), long.TryParse(), etc.

Votre cloud utilise également simplement un StringBuilder si vous voulez un format non statique.StringBuilder.AppendFormat()

String.Format doit être une méthode statique car les chaînes sont immuables. En faire une méthode d'instance impliquerait que vous puissiez l'utiliser pour "formater" ou modifier la valeur d'une chaîne existante.Cela, vous ne pouvez pas le faire, et en faire une méthode d'instance renvoyant une nouvelle chaîne n'aurait aucun sens.C'est donc une méthode statique.

String.Format prend au moins une chaîne et renvoie une chaîne différente.Il n'est pas nécessaire de modifier la chaîne de format pour renvoyer une autre chaîne, cela n'a donc pas de sens de le faire (en ignorant votre formatage).D'un autre côté, il ne serait pas si difficile de faire en sorte que String.Format être une fonction membre, sauf que je ne pense pas que C# autorise les fonctions membres const comme le fait C++.[Veuillez me corriger ainsi que ce message si c'est le cas.]

Les chaînes .NET sont immuables

Par conséquent, avoir une méthode d’instance n’a absolument aucun sens.

String foo = new String();

foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method. 

string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top