Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning values with a Func Delegate

In an effort to learn more about Func Delegates and Expression trees, I put together a simple example, however I am not getting the results I expect. Below is my code that has a Func that expects a Params class and a List of Products. The idea is to apply the Params Class as a filter against a list of Products. As I said, this is just an exercise for me to learn how all this works.

I am expecting the delegate to return a least one Product object, however it returns null.

static void Main(string[] args)
{
   Products products = CreateProducts();

   Params param = new Params { Val = "ABC"};

   Func<Params, Products, IEnumerable<Product>> filterFunc = 
       (p, r) => r.Where(x => x.Sku == p.Val).AsEnumerable();

   Products prods = filterFunc(param, products).ToList() as Products;// returns null
}


private static Products CreateProducts() 
{
   return new Products 
   {
       new Product{
           Price = 25.00,
           Sku = "ABC"
       },
       new Product{
           Price = 134.00,
           Sku = "DEF"
       }
    };
}

classes:

public class Params 
{
    public String Val { get; set; }
}

public class Products : List<Product> 
{
}

public class Product 
{
    public String Sku { get; set; }
    public double Price { get; set; }
}
like image 508
PhillyNJ Avatar asked Dec 21 '13 15:12

PhillyNJ


2 Answers

The problem is that ToList returns a List<Product>, but that's a distinctly different type than Products. You could provide a constructor of Products which accepts an IEnumerable<Product> like this:

public class Products : List<Product> {
    public Products(IEnumerable<Product> products) : base(products) {
    }
}

Products prods = new Products(filterFunc(param, products));

But if this is all your Products class does, it's probably a lot simpler to just get rid of it entirely and deal with IEnumerable<Product> (or List<Product>) wherever you need to handle a collection of Product objects:

IEnumerable<Product> products = CreateProducts();
Params param = new Params { Val = "ABC"};
Func<Params, IEnumerable<Product>, IEnumerable<Product>> filterFunc = 
    (p, r) => r.Where(x => x.Sku == p.Val);
IEnumerable<Product> prods = filterFunc(param, products);

private static IEnumerable<Product> CreateProducts() 
{
    return new Products[] {
        new Product{
            Price = 25.00,
            Sku = "ABC"
        },
        new Product{
            Price = 134.00,
            Sku = "DEF"
        },
    };
}
like image 172
p.s.w.g Avatar answered Oct 08 '22 06:10

p.s.w.g


Your call to .ToList() will return a List<Product>, not a Products (whatever that is), thus the call to as Products will fail its cast and will return null.

Products prods = filterFunc(param, products).ToList() as Products;// returns null

This might work (depending on the definition of Products which you haven't supplied:

List<Product> prods = filterFunc(param, products).ToList();

Or possibly (if products has a constructor that accepts an IEnumerable):

Products prods = new Products(filterFunc(param, products));
like image 27
jessehouwing Avatar answered Oct 08 '22 05:10

jessehouwing