Tomas
Tomas

Reputation: 18097

Linq Union do not work

I am trying to use Linq Union to add additional record into result but Union do not work. Maybe someone could point me in right direction.

        public class ProductView
                    {
                        public int Id { get; set; }
                        public bool Active { get; set; }
                        public string Name { get; set; }
                        public int ProductTypeId { get; set; }
                        public int UserCount { get; set; }

        }

void Main()
{


var product = Products.Select(p => new ProductView
   {
        Id = p.Id,
        Active = p.Active,
        Name = p.Name,
        ProductTypeId = p.ProductTypeId,
        UserCount = 1
   }).ToList();


    //The new item is not jointed to the result above   
    product.Union(new[] {
            new ProductView
            {
            Id = 9999,
            Active = true, 
            Name = "Test",
            ProductTypeId=0,
            } 
         });


 product.Dump();                                          
}

Upvotes: 2

Views: 1545

Answers (2)

Stuart
Stuart

Reputation: 66882

You need to store the output:

 var product2 = product.Union(new[] {
    new ProductView
    {
    Id = 9999,
    Active = true, 
    Name = "Test",
    ProductTypeId=0,
    } 
 });

 product2.Dump();

In addition to this, overriding the Equals behaviour would be useful - as you probably want to check equality using just the Id field?


For example, if you don't override the Equals behaviour, then you will get Object reference equals like this:

void Main()
{

    var list = new List<Foo>()
    {
    new Foo() { Id = 1},
    new Foo() { Id = 2},
    new Foo() { Id = 3},
    };

    var list2 = new List<Foo>()
    {
    new Foo() { Id = 1},
    new Foo() { Id = 2},
    new Foo() { Id = 3},
    };

    var query = list.Union(list2);

    query.Dump();

}

// Define other methods and classes here

public class Foo
{
 public int Id {get;set;}
}

produces six items!

But if you change Foo to:

public class Foo
{
    public int Id {get;set;}

    public override bool Equals(object obj)
    {
     if (obj == null || !(obj is Foo)) return false;
     var foo= (Foo)obj;
     return this.Id == foo.Id;
    }

    public override int GetHashCode()
    {
         return this.Id.GetHashCode();
    }    
}

then you will get 3 items - which is probably what you are expecting.

Upvotes: 4

Tim Schmelter
Tim Schmelter

Reputation: 460068

You need to override Equals and GetHashCode in ProductView if you want to use Union in a meaningful way(other than comparing by refence).

public class ProductView
{
    public int Id { get; set; }
    public bool Active { get; set; }
    public string Name { get; set; }
    public int ProductTypeId { get; set; }
    public int UserCount { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is ProductView)) return false;
        ProductView pv2 = (ProductView)obj;
        return this.Id == pv2.Id;
    }

    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
}

You could also implement an IEqualityComparer<ProductView> in a similar way and use it for this overload of Union.

Upvotes: 1

Related Questions