如何将Linq查询传递给一个方法?

13

我想将一个 Linq 查询传递给一个方法,如何指定参数类型?

我的Linq查询类似于:

var query =
    from p in pointList
    where p.X < 100
    select new {X = p.X, Y = p.Y}

显然我对Linq很陌生,当我转换我的其余代码时,最终可能会摆脱接收方法,但这似乎是我应该了解的东西...

谢谢


你想将查询结果传递给方法,还是想将查询传递给方法(以便该方法可以在数据源上使用该查询)? - Daniel Earwicker
5个回答

22
你需要使用普通类型来进行投影,或者使你传递的方法也成为泛型(这意味着你不能做太多事情)。你到底想做什么?如果你需要使用该方法中的X和Y值,你肯定需要创建一个普通类型。(虽然有可怕的hacky方法可以避免,但这不是一个好主意。)
注意:一些其他答案目前正在讨论IQueryable,但没有迹象表明你正在使用除LINQ to Objects之外的任何东西,在这种情况下,它将是IEnumerable - 但T目前是匿名类型。如果你想在每个项目中使用单独的值,那就是你需要解决的问题。如果你没有使用LINQ to Objects,请澄清问题,我会编辑这个答案。
例如,采用你当前的查询(稍微有点问题,因为你不能使用两个具有相同名称X的投影初始化器)。你需要创建一个新类型,例如MyPoint。
public sealed class MyPoint
{
    private readonly int x;
    private readonly int y;
    public int X { get { return x; } }
    public int Y { get { return y; } }

    public MyPoint(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

您的查询将会是:

您的查询将会是:

var query =
    from p in pointList
    where p.X < 100
    select new MyPoint(p.X, p.Y);

那么你的方法应该写成这样:

public void SomeMethod(IEnumerable<MyPoint> points)
{
    ...
}

并将其称为SomeMethod(query);


这么多人不同意Jon,这真的可能吗?我的意思是你几乎写了C#的“圣经”啊。 - Samuel
我正在尝试逐步将代码转换为使用linq,同时在测试过程中进行测试。现在我已经将数据集设置为调用序列的开头,因此最终需要将其转换为旧代码的一半。看起来我最好是全部转换然后再进行测试。 - Oskar
2
@Samuel:很多人看到“LINQ”就会立刻想到“LINQ to SQL”(或实体框架等)。个人而言,我发现LINQ to Objects对日常工作更有用 :) - Jon Skeet
我同意Jon的观点,只是在他之前回答了问题...而且我还得纠正我的答案。 - irperez
非常好的答案,你展示的技巧是选择一个非泛型类型,然后我回到了旧版C#。现在我的代码可以工作了,我将继续转换其余的代码,但很可能很快就会回来询问动态创建查询(匹配相同结果类型)的问题。 - Oskar

3

我认为你要找的是Expression类。例如,

public void DoSomething()
{
    User user = GetUser(x => x.ID == 12);
}

IQueryable<User> UserCollection;

public User GetUser(Expression<Func<User,bool>> expression)
{
    return UserCollection.expression;
}

2
public void DoSomething(IQueryable query) { ... }

public void DoSomething<T>(IQueryable<T> query) { ... }

如果你需要传递表达式,请参考以下内容:

public void DoSomething(Expression exp) { ... }

“query”的类型肯定不是Expression。它很可能是IEnumerable<T>或IQueryable<T>。 - Jon Skeet
3
没问题,我想他可能也对传达表达方式感兴趣,这可能是他接下来要问的问题 :) - Konstantin Tarkus

1

tvanfosson和Jon都是正确的,你可以编写一个接受 IEnumerable<T> 的函数(你可以将函数定义为泛型或者指定具体的泛型版本,后者更可能是正确的选项),因为LINQ to Objects生成的是 IEnumerable<T>,而LINQ to SQL生成的是实现了 IEnumerable<T>IQueryable<T>。这个选项应该可以让你不用考虑数据源。


0

你也可以使用以下代码:

    IEnumerable <TableName> result = from x in dataBase.TableName
                                     select x;     
    methodName(result);



    private void methodName (IEnumerable<TableName> result) 
    {
      codes.....
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接