Donc, je pense (je pense) comprendre ce que fait le modificateur de paramètre in
. Mais ce qu'il fait semble être tout à fait redondant.
Généralement, je pense que la seule raison d'utiliser un ref
serait de modifier la variable appelante, ce qui est explicitement interdit par in
. Donc, passer par in
référence semble logiquement équivalent à passer par valeur.
Existe-t-il un avantage en termes de performances? J’étais convaincu que du côté des choses, un paramètre ref
doit au moins copier l'adresse physique de la variable, qui devrait avoir la même taille que tout objet typique. référence.
Alors, l'avantage est-il uniquement dans les grandes structures, ou existe-t-il une optimisation en arrière-plan du compilateur qui la rend attrayante ailleurs? Si ce dernier cas, pourquoi ne devrais-je pas créer tous les paramètres d'un in
?
in
a récemment été introduit dans le langage C #.
in
est en fait un ref readonly
. D'une manière générale, il n'y a qu'un seul cas d'utilisation où in
peut être utile: des applications hautes performances traitant beaucoup de grands readonly struct
S.
En supposant que vous ayez:
readonly struct VeryLarge
{
public readonly long Value1;
public readonly long Value2;
public long Compute() { }
// etc
}
et
void Process(in VeryLarge value) { }
Dans ce cas, la structure VeryLarge
sera passée par référence sans créer de copies défensives lors de l'utilisation de cette structure dans la méthode Process
(par exemple lors de l'appel de value.Compute()
), et l'immuabilité de la structure est assurée par le compilateur.
Notez que passer un struct
non lu avec un modificateur in
force le compilateur à créer une copie défensive lorsque l'appel des méthodes de struct et l'accès aux propriétés dans la méthode Process
ci-dessus, ce qui affectera négativement les performances!
Il y a un très bon entrée de blog MSDN que je recommande de lire attentivement.
Si vous souhaitez obtenir plus d'informations sur l'historique de in
-, vous pouvez lire ceci discussion dans le référentiel GitHub du langage C #.
En général, la plupart des développeurs s'accordent à dire que l'introduction de in
pourrait être considérée comme une erreur. C'est un langage plutôt exotique et ne peut être utile que dans les cas Edge très performants.
passer par
in
référence semble logiquement équivalent à passer par valeur.
Correct.
Existe-t-il un avantage en termes de performances?
Oui.
J’étais convaincu que du côté de l’arrière-plan, un paramètre
ref
devait au moins copier l’adresse physique de la variable, qui devait avoir la même taille que toute référence d’objet typique.
Il n’existe pas de condition qu’une référence à un objet et une référence à une variable aient la même taille et qu’il n’existe pas de exigence soit la taille d'un mot machine, mais oui, en pratique, les deux sont 32 bits sur des machines 32 bits et 64 bits sur des machines 64 bits.
Ce que vous pensez que "l'adresse physique" a à voir avec cela ne me semble pas clair. Sous Windows, nous utilisons des adresses virtuelles , pas adresses physiques dans le code en mode utilisateur. Je suis curieux de savoir dans quelles circonstances possibles imagineriez-vous qu'une adresse physique a une signification dans un programme C #?.
Il n’existe pas non plus d’implémentation d’une référence de quelque type que ce soit en tant qu’adresse virtuelle du stockage. Les références peuvent être des poignées opaques dans des tables GC dans une implémentation conforme de la spécification CLI.
l'avantage est-il juste dans les grandes structures?
Le scénario de motivation (- === -) de la fonctionnalité permet de réduire le coût de passage de structures plus grandes.
Notez qu'il n'y a aucune garantie que in
accélère réellement les programmes et puisse les ralentir. Toutes les questions sur les performances doivent être résolues par des recherches empiriques. Il y a très peu d'optimisations qui sont toujours gagnantes ; ce n'est pas une optimisation "toujours gagnante".
existe-t-il une optimisation en arrière-plan du compilateur qui le rend attrayant ailleurs?
Le compilateur et le moteur d'exécution sont autorisés à effectuer les optimisations qu'ils choisissent si cela ne viole pas les règles de la spécification C #. À ma connaissance, il n’ya pas encore d’optimisation de ce type pour les paramètres in
, mais cela n’empêche pas de telles optimisations à l’avenir.
pourquoi ne devrais-je pas transformer chaque paramètre en?
Supposons que vous ayez créé un paramètre int
à la place un in int
paramètre. Quels coûts sont imposés?
Supposons que c’est un double
et que vous le changez en un in double
. Encore une fois, la variable ne peut plus être inscrite dans un registre à virgule flottante hautes performances. Cela a non seulement des conséquences sur les performances , mais il peut aussi changer le comportement du programme! C # est autorisé à utiliser l'arithmétique des flottants avec une précision supérieure à 64 bits et ne le fait généralement que si les flottants peuvent être enregister.
Ce n'est pas une optimisation gratuite. Vous devez mesurer ses performances par rapport aux alternatives. Votre meilleur pari est tout simplement de ne pas créer de grandes structures en premier lieu, comme le suggèrent les directives de conception.
Il y a. Lors du passage d'un struct
, le mot clé in
permet une optimisation lorsque le compilateur n'a besoin que de passer un pointeur, sans risque de modification du contenu par la méthode. est critique - cela évite une opération de copie. Sur de grandes structures, cela peut faire toute la différence.
Ceci est fait en raison de l'approche de programmation fonctionnelle. L'un des principes majeurs est que la fonction ne doit pas avoir d'effets secondaires, ce qui signifie qu'elle ne doit pas modifier les valeurs des paramètres et doit renvoyer une valeur. En C #, il n'y avait aucun moyen de passer des structures (et un type de valeur) sans être copié uniquement par référence, ce qui permet de modifier la valeur. Dans Swift, il existe un algorithme de hacky qui copie struct (leurs collections sont des structures BTW) tant que la méthode commence à changer ses valeurs. Les personnes qui utilisent Swift pas toutes Ceci est une fonctionnalité intéressante de c # car sa mémoire est efficace et explicite. Si vous regardez quoi de neuf , vous verrez que de plus en plus de choses sont effectuées autour des structures et des tableaux en pile. Une déclaration est simplement nécessaire pour ces fonctionnalités. Des limitations sont mentionnées dans les autres réponses, mais ce n’est pas essentiel pour comprendre l’orientation de .net.