【问题标题】:Returning values with a Func Delegate使用 Func 委托返回值
【发布时间】:2014-01-10 07:33:02
【问题描述】:

为了了解更多关于 Func Delegates 和 Expression 树的信息,我整理了一个简单的例子,但是我没有得到我期望的结果。下面是我的代码,它有一个 Func,它需要一个 Params 类和一个产品列表。这个想法是应用 Params 类作为产品列表的过滤器。正如我所说,这只是一个练习,让我了解这一切是如何运作的。

我希望委托返回至少一个 Product 对象,但它返回 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"
       }
    };
}

类:

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; }
}

【问题讨论】:

  • 您的filterFunc 没有问题... 但ToList() 将返回List&lt;Product&gt; 的实例,而List&lt;Product&gt;Products 的类型不同,因此as Products表达式总是返回null...
  • List&lt;Product&gt; prods = filterFunc(param, products).ToList() 是否也为空?

标签: c# linq delegates func


【解决方案1】:

问题是ToList 返回一个List&lt;Product&gt;,但它与Products 截然不同。您可以提供Products 的构造函数,它接受IEnumerable&lt;Product&gt;,如下所示:

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

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

但是,如果这是您的所有 Products 类,那么完全摆脱它并处理 IEnumerable&lt;Product&gt;(或 List&lt;Product&gt;)可能要简单得多,因为您需要处理 Product 的集合对象:

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"
        },
    };
}

【讨论】:

    【解决方案2】:

    您对.ToList() 的调用将返回List&lt;Product&gt;,而不是Products(无论如何),因此对as Products 的调用将失败并返回null

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

    这可能有效(取决于您尚未提供的 Products 的定义:

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

    或者可能(如果产品具有接受 IEnumerable 的构造函数):

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

    【讨论】:

      【解决方案3】:

      Func 中,您正在使用Where 方法,该方法接受IEnumerable&lt;T&gt; 和条件,然后返回IEnumerable&lt;T&gt;。它将输入可枚举包装在另一个可枚举中,这限制了基础可枚举的元素数量,因此返回的对象实现 IEnumerable 但不是输入对象的类型(在您的情况下为产品)。

      如果无法执行强制转换,使用as 运算符会给出 null。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 2012-03-04
        相关资源
        最近更新 更多