【问题标题】:Using Linq to run a method on a collection of objects?使用 Linq 在对象集合上运行方法?
【发布时间】:2009-06-23 12:34:56
【问题描述】:

这是一个远射,我知道......

假设我有一个收藏

List<MyClass> objects;

我想在集合中的每个对象上运行相同的方法,无论有没有返回值。在 Linq 之前我会说:

List<ReturnType> results = new List<ReturnType>();
List<int> FormulaResults = new List<int>();
foreach (MyClass obj in objects) {
  results.Add(obj.MyMethod());
  FormulaResults.Add(ApplyFormula(obj));
}

我希望喜欢能够做这样的事情:

List<ReturnType> results = new List<ReturnType>();
results.AddRange(objects.Execute(obj => obj.MyMethod())); 
// obviously .Execute() above is fictitious
List<int> FormulaResults = new List<int>();
FormulaResults.AddRange(objects.Execute(obj => ApplyFormula(obj)));

我还没有找到任何可以做到这一点的东西。有这种事吗?

如果没有像我上面所说的那样通用,至少也许有一种方法可以用于我现在正在研究的目的:我有一个具有包装类的对象的集合:

class WrapperClass {
  private WrappedClass wrapped;
  public WrapperClass(WrappedClass wc) {
    this.wrapped = wc;
  }
}

我的代码有一个集合List&lt;WrappedClass&gt; objects,我想将其转换为List&lt;WrapperClass&gt;。有没有一些聪明的 Linq 方法可以做到这一点,而不用做繁琐的操作

List<WrapperClass> result = new List<WrapperClass>();
foreach (WrappedClass obj in objects)
  results.Add(new WrapperClass(obj));

谢谢...

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    会:

    results.AddRange(objects.Select(obj => ApplyFormula(obj)));
    

    做吗?

    或(更简单)

    var results = objects.Select(obj => ApplyFormula(obj)).ToList();
    

    【讨论】:

      【解决方案2】:

      我认为 Select() 扩展方法可以满足您的需求:

      objects.Select( obj => obj.MyMethod() ).ToList(); // produces List<Result> 
      
      objects.Select( obj => ApplyFormula(obj) ).ToList(); // produces List<int>
      

      最后一种情况也是这样:

      objects.Select( obj => new WrapperClass( obj ) ).ToList();
      

      如果您有一个想要调用的 void 方法,您可以使用以下技巧与 IEnumerable 一起使用,它没有 ForEach() 扩展,无需太多努力即可创建类似的行为。

      objects.Select( obj => { obj.SomeVoidMethod(); false; } ).Count();
      

      在对象序列中的每个[obj] 上调用SomeVoidMethod() 后,Select() 将产生一系列[false] 值。由于Select() 使用延迟执行,我们调用Count() 扩展来强制评估序列中的每个元素。当您想要 ForEach() 之类的行为时,它非常有效。

      【讨论】:

        【解决方案3】:

        如果您要应用的方法MyMethod 返回一个T 类型的对象,那么您可以通过以下方式获得该方法结果的IEnumerable&lt;T&gt;

        var results = objects.Select(o => o.MyMethod());
        

        如果您要应用的方法MyMethod 的返回类型为void,那么您可以通过以下方式应用该方法:

        objects.ForEach(o => o.MyMethod());
        

        这假定objects 是泛型类型List&lt;&gt;。如果你只有一个IEnumerable&lt;&gt;,那么你可以roll your own ForEach 扩展方法或先应用objects.ToList() 并使用上述语法。

        【讨论】:

          【解决方案4】:

          C# 编译器将 LINQ 选择映射到 .Select 扩展方法上,该方法通过 IEnumerable(或 IQueryable,我们将在此处忽略)定义。实际上,那个 .Select 方法正是你所追求的那种投影函数。

          LBushkin 是正确的,但实际上您也可以使用 LINQ 语法...

          var query = from o in objects
             select o.MyMethod();
          

          【讨论】:

            【解决方案5】:

            您还可以使用奇妙的 Jon Skeet 的 morelinq library 运行自定义方法

            例如,如果您的 MyClass 上有一个文本属性,您需要在运行时使用同一类上的方法进行更改:

            objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList();
            

            此方法现在将在列表中的每个对象上实现。我爱morelinq!

            【讨论】:

              【解决方案6】:

              http://www.hookedonlinq.com/UpdateOperator.ashx 有一个可以使用的扩展更新方法。或者您可以使用其他人发布的 select 语句。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-12-03
                • 1970-01-01
                • 2010-09-05
                相关资源
                最近更新 更多