2017-07-12 3 views
2

Pourquoi les variables out ne sont pas autorisées dans la clause de requête?C# 7 Les déclarations de variable de variable et de variable de modèle ne sont pas autorisées dans une clause de requête

Si je sur les variables ici, il échoue:

string json = "{'PayDays':['2017-07-07','2017-07-21','2017-08-04','2017-08-18']}"; 
var pd = JsonConvert.DeserializeObject<Accounting>(json); 

var rm = from item in pd.PayDays 
    where (DateTime.TryParse(item, out DateTime dateresult)) ? 
    dateresult.Subtract(DateTime.Now).Days >= 0 ? true : false : false  
    select item; 
rm.Dump(); 

Mais ancienne fonctionne:

DateTime result; 
var rm = from item in pd.PayDays 
     where DateTime.TryParse(item, out result) ? (result.Subtract(DateTime.Now).Days >= 0 ? true : false) : false 
     select item; 
rm.Dump(); 

Répondre

8

Voici les relevant LDM notes.

La conclusion:

Nous n'aurons pas le temps de faire cette fonction en C# 7.0. Si nous voulons nous laisser la possibilité de le faire à l'avenir, nous devons nous assurer que nous n'autorisons pas les variables d'expression dans les clauses de requête à signifier autre chose aujourd'hui, qui contredirait un tel futur.

La sémantique actuelle est que les variables d'expression dans les clauses de requête sont limitées à la clause de requête. Cela signifie que deux prochaines requêtes peuvent utiliser le même nom dans les variables d'expression, par exemple. Cela n'est pas cohérent avec un futur qui permet à ces variables de de partager une étendue entre les limites de la clause de requête.

Ainsi, si nous voulons permettre cela à l'avenir, nous devons mettre des restrictions dans C# 7.0 pour protéger l'espace de conception. Nous avons quelques d'options:

  • variables d'expression Rejeter tout à fait dans les clauses de requête
  • Exiger que toutes les variables d'expression dans une expression de requête donnée ont des noms

Le premier est un grand marteau, mais ce dernier exige beaucoup de travail pour obtenir le droit - et semble à risque de ne pas bloquer tout assez bien.

et

Nous non plus des variables d'expression ni deconstruction en C# 7.0, mais voudrions les faire à l'avenir.Afin de protéger notre capacité à le faire, nous allons complètement interdire les variables d'expression dans les clauses de requête, même si c'est un gros marteau.

0

Le problème est que la traduction vous a montré fonctionne bien pour LINQ normale à des objets, mais il être problématique pour d'autres fournisseurs, comme PLINQ ou Entity Framework.

Par exemple, considérons la traduction que vous proposez pour votre requête modifiée pour utiliser PLINQ:

DateTime result; 
var rm = from item in pd.PayDays.AsParallel() 
     where DateTime.TryParse(item, out result) ? (result.Subtract(DateTime.Now).Days >= 0 ? true : false) : false 
     select item; 
var list = rm.ToList(); 

Ce code est thread-safe, parce que plusieurs threads partagent une seule variable de result et vous allez probablement obtenir des résultats incorrects, car ils vont essayer de l'utiliser en même temps.

Il existe des moyens de traduire correctement de telles requêtes, au moins dans certains cas, mais elles ne sont pas triviales. Par conséquent, les variables out ne sont tout simplement pas autorisées dans la syntaxe de requête LINQ. Bien que there is a proposal to allow them in a future version of C#.

+0

Du point de vue linguistique, la traduction semble assez simple: l'équivalent de 'du poste dans pd.PayDays.AsParallel() let resultHolder = new displayclass() où DateTime.TryParse (point, sur resultHolder.result)? ...: ... select item; ', avec le même type de classes' DisplayClass' générées qui sont déjà générées pour d'autres raisons. Pouvez-vous donner un exemple où cette approche simple ne fonctionnerait pas ou se comporterait de manière inattendue? – hvd