0

Both snippets of code work, however, I'm wondering which one is a better(if any). Is there a real difference? The part of the code I'm referring to is in the LINQ. Any insight would be appreciated.

select new Product {...

First Snippet:

public static IEnumerable<Product> GetProducts(IEnumerable<Product> products)
{
    var query = from p in products
                select new Product
                {
                    Category = p.Category,
                    Id = p.Id,
                    CategoryId = p.CategoryId,
                    Name = p.Name
                };
    return query;
}


class Product
{
    public int Id { get; set; }
    public String Name { get; set; }
    public Category Category { get; set; }
    public int CategoryId { get; set; }
}

class Category
{
    public int Id { get; set; }
    public String CategoryName { get; set; }
} 

Second Snippet:

 public static IEnumerable<Product> GetProducts(IEnumerable<Product> products)
    {
        var query = from p in products
                    select p;
        return query;
    }


class Product
{
    public int Id { get; set; }
    public String Name { get; set; }
    public Category Category { get; set; }
    public int CategoryId { get; set; }
}

class Category
{
    public int Id { get; set; }
    public String CategoryName { get; set; }
}
4
  • It seems products is IEnumerable<Product>. What is the reason generating product class in snippet1? Commented Jan 2, 2013 at 23:37
  • By the way, none of the approaches uses anonymous objects. Title seems a bit misleading? Commented Jan 2, 2013 at 23:38
  • @sylon There's no such thing as an "anonymous object" anyway -- presumably the new Product { syntax reminds the OP of anonymous classes, but of course those are not being used here either. Rather, this construct is called an object initializer. Commented Jan 2, 2013 at 23:39
  • @sylon good point...I should retitle. Commented Jan 2, 2013 at 23:42

1 Answer 1

1

The first snippet will return a query that will, when enumerated, create a copy of each object in the products enumerable, and iterate over those copies. (Caveat: If the input objects are of a type derived from Product and not actually Product itself, then you will "slice" those objects into instances of Product.)

The second snippet will return a query that will, when enumerated, iterate over the objects in the original sequence, and really isn't semantically different from doing return products; (assuming that products is not null, that is -- both variations would throw an exception when enumerated if products was null, but would throw a different exception type).

The "tl;dr" version is: the first approach copies the objects in the sequence, the second one does not.

Use the first when you need to make a deep copy of a sequence so that modifying the objects in the resulting sequence do not modify the objects in the original sequence. Use the second approach if you do, in fact, want modifications to affect the original sequence, or you will not be modifying either of the two sequences.


Aside: If you do need to take copies, consider creating a virtual method on the Product class (public virtual Product Clone()) so that (a) the cloning logic is encapsulated, and (b) if you derive Product, you can override Clone() to return a properly-typed copy.

Sign up to request clarification or add additional context in comments.

1 Comment

Seems like a good response. I appreciate the answer and have a better understanding.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.