7
votes

"Impossible d'utiliser une expression Lambda locale fixe"

J'ai un projet XNA 3.0 qui compilait juste bien dans VS2008, mais cela donne des erreurs de compilation dans VS2010 (avec XNA 4.0 CTP). L'erreur:

Impossible d'utiliser "STAPTPR" local fixe dans une méthode anonyme, une expression Lambda ou une expression de requête

STAPTPTR est un flotteur fixe * dans un tableau, utilisé à l'intérieur d'un parallel.for Expression Lambda de < Code> System.threading . Comme je l'ai dit, cela compilait et couru juste bien sur VS2008, mais ce n'est pas sur VS2010, même lorsque vous ciblez .NET 3.5.

a-t-il changé dans .NET 4.0, et même si, ne devrait-il pas toujours compiler lorsque je choisis .NET 3.5 comme cadre cible? La recherche du terme "ne peut pas utiliser" local fixe "des rendements exactement un résultat (inutile), à ​​la fois dans Google et Bing.

Si cela a changé, quelle est la raison pour cela? Je peux imaginer capturer un fixe de type pointeur dans une fermeture pourrait être un peu bizarre, c'est pourquoi? Donc, je suppose que c'est une mauvaise pratique? Et avant que quiconque ne demande: non, l'utilisation de pointeurs n'est pas absolument critique ici. Je voudrais toujours savoir cependant :)

EDIT: Comme demandé, un échantillon de code (non de mon programme, évidemment) qui reproduit l'erreur suivante: xxx

La compile ci-dessus dans VS2008 (Eh bien, à part la référence à Parallèle , mais toute autre expression de Lambda fera), mais ne va pas dans VS2010.


3 commentaires

Pouvez-vous s'il vous plaît poster le code qui provoque l'erreur.


Eh bien, il n'y a pas grand chose à poster, c'est exactement ce que l'erreur a dit: l'utilisation d'un pointeur dans une expression lamdba.


Néanmoins, poster un code court mais complet que nous pouvons expérimenter serait une bonne chose (TM).


5 Réponses :


0
votes

Une explication pourrait être que la valeur d'une variable est prise à l'exécution de la fermeture et non la définition. Dans votre exemple, cela ne ferait probablement aucun mal, mais dans d'autres cas, cela pourrait être. Donc, pour enseigner la bonne pratique, il est complètement interdit d'empêcher toutes sortes de bugs intéressants.


0 commentaires

3
votes

Pinceaux fixes un pointeur pendant la durée du bloc. Si vous deviez stocker le délégué pour invoquer ultérieurement après l'évolution du bloc, le collecteur des ordures pourrait déplacer l'objet entre la lecture de la Lambda et lorsque la Lambda est invoquée. Pourquoi cibler un cadre différent n'aide pas, c'est parce que cela est en cours d'exécution par la langue / le compilateur, pas le temps d'exécution (s'il s'agissait de l'exécution, il serait signalé via une exception ou similaire au moment de l'exécution, pas par le compilateur au moment de la compilation).


2 commentaires

Ah, donc il définit simplement la version d'exécution et n'utilise pas un plus ancien compilateur? Logique. À propos de l'épinglage, oui, c'est un risque, mais je pourrais tout aussi bien déclarer un champ d'instance sur le type qui vit également plus longtemps que le bloc fixe, ce qui lui permet d'indiquer un emplacement invalide. Pourtant, c'est toujours possible.


Je ne pense pas qu'il serait possible de vérifier statiquement tous les scénarios qu'un pointeur épinglé pourrait devenir invalide, finalement, une personne peut toujours utiliser Gchandle. Ce chèque représente probablement simplement un "meilleur effort" pour éviter les problèmes non évidents qui peuvent s'ensuivre du code comme celui-ci.



1
votes

the DOCO Dites Vous n'êtes pas autorisé à accéder à un code dangereux dans une méthode anonyme et les mêmes restrictions s'appliquent à Lambdas, alors je pense que cela peut être votre problème. Avez-vous l'erreur de compilateur non?


0 commentaires

2
votes

Cela fonctionne. Fondamentalement, nous avons éliminé la Lambda contenant un pointeur dangereux et l'a remplacé par un délégué à une instance d'une classe déclarée à l'intérieur du bloc (code> xxx

me ressemble. NET 4 Ajout d'une tentative de demi-arsed au moment d'intercalaire un accès à la mémoire fixe dans le compilateur. Dans le bloc de code ci-dessus, vous pouvez définir non rafare en dehors du bloc fixe fixe . Donc, ce n'est pas parfait ...


0 commentaires

1
votes

Le compilateur est correct de rejeter ce code. Fixe ne peut être utilisé que sur les variables locales et les variables capturées par une fermeture ne sont pas des variables locales, elles sont hissées dans la classe utilisée pour maintenir l'état pour la fermeture.


0 commentaires