2010-06-11 4 views
4

Je suis un débutant qui a finalement commencé à comprendre les types anonymes.Tuples ou types anonymes vs. objet Expando. (en ce qui concerne les requêtes LINQ)

(voir ancien poste What is the return type for a anonymous linq query select? What is the best way to send this data back?)

Ainsi, dans les requêtes LINQ vous formez le type de valeur de retour que vous voulez dans le droit de requête LINQ? Il semble que la façon de le faire est de type anonyme non?

Quelqu'un peut-il m'expliquer si et quand je pourrais utiliser un objet Tuple/Expando à la place? Ils semblent tous très simliar?

Répondre

3

Vous n'indiquez pas le contexte de votre question, je vais donc répondre à LinqToObjects et à LinqToSql.

Dans LinqToObjects, supposons que vous avez un List<Customer> source.

//Straight projection. 
    //no new instances are created when query is evaluated. 
IEnumerable<Customer> result = 
    from c in source where c.Name == "Bob" 
    select c; 

    //Different Type projection 
    //a new instance of CustomerName is created 
    // for each element in the result when the query is evaluated. 
IEnumerable<CustomerName> result = 
    from c in source where c.Name == "Bob" 
    select new CustomerName() {Name = c.Name}; 

    //Anonymous Type Projection  
    //a new instance of an anonymous type is created 
    // for each element in the result when the query is evaluated. 
    //You don't have access to the type's name 
    // since the compiler names the type, 
    // so you must use var to talk about the type of the result. 
var result = 
    from c in source where c.Name == "Bob" 
    select new {Name = "Bob"}; 

    //Tuple Projection (same as Different Type Projection) 
    //a new instance of Tuple is created 
    // for each element in the result when the query is evaluated. 
IEnumerable<Tuple<string, int>> result = 
    from c in source where c.Name == "Bob" 
    select new Tuple<string, int>(){First = c.Name, Second = c.Id}; 

En LinqToSql, supposons que vous avez un IQueryable<Customer> db.Customers

//Straight projection 
    //when the query is resolved 
    // DataContext.Translate<Customer> is called 
    // which converts the private dbReader into new Customer instances. 
IQueryable<Customer> result = 
    from c in db.Customers where c.Name == "Bob" 
    select c; 

    //Different Type Projection 
    //when the query is resolved 
    // DataContext.Translate<CustomerName> is called 
    // which converts the private dbReader into new CustomerName instances. 
    // 0 Customer instances are created. 
IQueryable<Customer> result = 
    from c in db.Customers where c.Name == "Bob" 
    select new CustomerName() {Name = c.Name}; 

    //Different Type Projection with a twist 
    //when the query is resolved 
    // DataContext.Translate<CustomerGroup> is called 
    // which converts the private dbReader into new CustomerGroup instances. 
    // 0 Customer instances are created. 
    //the anonymous type is used in the query translation 
    // yet no instances of the anonymous type are created. 
IQueryable<Customer> result = 
    from c in db.Customers 
    group c by new {c.Name, TheCount = c.Orders.Count()} into g 
    select new CustomerGroup() 
    { 
    Name = g.Key.Name, 
    OrderCount = g.Key.TheCount, 
    NumberInGroup = g.Count() 
    }; 

Ok, ça suffit pour l'instant.

+0

J'utilise linq2entities donc je pense que c'est comme votre premier exemple. Y at-il une raison ou un avantage d'utiliser tuple sur anonyme? – punkouter

+0

Les instances de types anonymes ne traversent pas très bien les limites de méthode. Les tuples n'ont aucun problème avec ça. –

+0

mais dans le cas de base de renvoyer un objet dans une requête linq rapide sans avoir à définir une nouvelle classe je suppose que c'est tout le point de types anon. – punkouter

4

Les tuples et les objets Expando ne sont normalement pas utilisés dans LINQ. Ils sont tous deux très différents des types anonymes.

Les types anonymes sont couramment utilisés pour "façonner" les requêtes LINQ; Par exemple, vous pouvez définir un type ayant une propriété string Name et une propriété int Age.

Les tuples sont des types qui agissent uniquement comme des structures de type «paire» ou «triplet». Par exemple, un Tuple<string, int> peut être défini, mais les noms des propriétés sont nommés Item1 et Item2, et non Name et Age. Les tuples ne sont normalement pas utilisés pour former des requêtes LINQ parce que ces noms de propriétés rendent le code moins clair.

ExpandoObject est totalement différent. Il vous permet d'ajouter des propriétés à l'exécution à un objet existant.

+0

Ok ça aide merci. Quels sont les avantages d'un tuple sur anonyme? Je suppose que cela a quelque chose à voir avec vous ne pouvez pas utiliser des types anonymes en dehors de la méthode? ou quelque chose? Expandoobject me semble lié au type dynamique qui n'a rien à voir avec les requêtes linq ... pensé peut-être si je reçois une requête linq de client et que je veux ajouter un entier 'rating' à la classe client que j'utiliserais expando/dynamique? Ce serait une raison de l'utiliser peut-être? – punkouter

+0

Il est vrai que les tuples peuvent être utilisés n'importe où, alors que les types anonymes sont limités à la méthode. Cependant, il est plus courant de définir son propre type de résultat avec des noms de champs significatifs. ExpandoObject est un type d'objet dynamique; alors qu'il peut être utilisé dans les requêtes LINQ (tout comme les types Tuple), ce n'est généralement pas le cas. Pour ajouter un champ dans une requête LINQ, il est plus fréquent de définir un nouveau type anonyme que d'utiliser ExpandoObject. Cela dit, EO est assez nouveau, donc cela peut devenir une approche plus populaire au fil du temps. –

+0

ok .. je me demandais juste si je pouvais trouver une excuse pour utiliser les nouvelles choses 4.0 .. – punkouter