Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# LINQ查询表达式和扩展方法之间有什么区别_C#_Linq_Query Expressions - Fatal编程技术网

C# LINQ查询表达式和扩展方法之间有什么区别

C# LINQ查询表达式和扩展方法之间有什么区别,c#,linq,query-expressions,C#,Linq,Query Expressions,下面是两个返回相同数据的查询。其他然后样式我不确定哪一个更好 哪些因素会影响这些查询? 使用一种样式比使用另一种样式有什么好处 样本1 var x = from s in db.Surveys join sq in db.Survey_Questions on s.ID equals sq.Survey_ID join q in db.Questions on sq.Question_ID equals q.ID join qg in db.Question_Groups

下面是两个返回相同数据的查询。其他然后样式我不确定哪一个更好

哪些因素会影响这些查询? 使用一种样式比使用另一种样式有什么好处

样本1

var x = from s in db.Surveys
    join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
    join q in db.Questions on sq.Question_ID equals q.ID
    join qg in db.Question_Groups on q.ID equals qg.Question_ID
    where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
    select new { question = sq.Question, status = sq.Status, grp = qg };
样本2

var x = db.Surveys.Where(s => s.Type_ID.Equals(typeID) & s.Type.Equals(type))
              .Join(db.Survey_Questions,
                        s => s.ID,
                        sq => sq.Survey_ID,
                        (s, sq) => new
                        {
                            question = sq.Question,
                            status = sq.Status
                        })
              .Join(db.Question_Groups,
                        q => q.question.ID,
                        qg => qg.Question_ID,
                        (q, qg) => new
                        {
                            question = q.question,
                            status = q.status,
                            group = qg
                        }).ToList();

LINQ是一种技术的流行语

IQueryable是LINQ使用的.NET接口

除了风格,两者之间没有区别。用你喜欢的样式


我更喜欢第一种风格的长语句(如图所示),第二种风格的短语句。

我认为你的问题更适合这样表述:“对于LINQ,IEnumerable和IQueryable之间有什么区别?”


默认情况下,LINQ查询返回IQueryable。IQueryable允许您在执行查询之前将其他筛选器或“子句”附加到查询中

您的LINQ查询(第一个示例)和使用方法链接的LINQ(第二个示例)使用不同的语法生成相同的结果

可以将LINQ查询编写为LINQ方法链,反之亦然。这取决于你的喜好


@Lucas:不同的是IEnumerable执行内存内查询,而IQueryable执行内存外查询。这意味着,一旦您在一个
foreach
迭代器中,您就在使用IEnumerable,当您通过扩展方法或使用对象中o的LINQ
构建查询时,您正在构建一个IQueryable。只要触摸枚举器,IQueryable就会立即执行。

1./您的问题标题与您提出的问题不匹配。
2./你的问题标题没有真正意义。Linq代表语言集成查询,是一组技术和实践的总称,IQueryable是一个常用于促进Linq的接口。你在比较苹果和橙子

3./关于您的实际问题,主要区别在于风格,对于像这样的复杂查询,我个人的偏好是第二个版本,因为它清楚地显示了结果集的进程。

第一个示例中的where子句实际上只是第二个方法中where子句的语法糖。事实上,您可以编写自己的类,它与Linq或IQueryable无关,只需使用Where方法,就可以使用这种语法糖。例如:

    public class MyClass
    {

        public MyClass Where<T>(Func<MyClass, T> predicate)
        {
            return new MyClass { StringProp = "Hello World" };
        }

        public MyClass Select<T>(Func<MyClass, T> predicate)
        {
            return new MyClass ();
        }



        public string StringProp { get; set; }
    }

这将导致写下“Hello World”。同样,这个例子显然毫无意义,但它证明了一点,“where”语法只是在代码中查找接受Func的where方法。

查询表达式和扩展方法是完全相同的两种方法。在编译时,查询表达式会转换为扩展方法——对于更熟悉SQL的人来说,它们只是语法糖

当你写这篇文章时:

var surveyNames = from s in db.Surveys select s.Name;
编译器将其转换为:

IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
IQueryable surveryNames=db.Surveys.Select(s=>s.Name);

事实上,我认为查询表达式只是出于市场原因而创建的——一种类似SQL的语言结构,在开发LINQ时起到了吸引眼球的作用,而不是提供很多实际用途。我发现大多数人只是直接使用扩展方法,因为它们产生了更统一的编码风格,而不是C#和SQL的混合。

更新:您已经修复了标题,所以忽略这个问题

问题的标题与代码示例无关。您的问题暗示一种语法是IEnumerable,另一种是IQueryable,但这是不正确的。在示例中,如果
db.Surveys
是IQueryable,则两个示例都使用IQueryable。我将尝试回答这两个问题

您的两个代码示例只是编写相同LINQ查询的不同方式(假设它们编写得很好)。示例1中的代码只是示例2中代码的简写。编译器以相同的方式处理两个示例中的代码。想想C#编译器将如何处理
int?
Nullable
一样。C#和VB.Net语言都提供了这种速记查询语法。其他语言可能没有这种语法,您必须使用示例2语法。事实上,其他语言甚至可能不支持扩展方法或lambda表达式,您还必须使用更难看的语法


更新:

进一步以Sander的例子为例,当您编写此(查询理解语法)时:

您认为编译器会将简写转换为以下内容(扩展方法和lambda表达式):

此外,扩展方法语法可以更灵活,例如条件where子句:

var items = source.Where(s => s > 5);

if(smallerThanThen)
    items = items.Where(s => s < 10);
if(even)
    items = items.Where(s => (s % 2) == 0);

return items.OrderBy(s => s);
另一方面,当查询变得更大、更复杂时,查询理解语法会更清晰,特别是当您开始使用一些
let
group
join
等使其复杂化时

最后,对于每个特定的查询,我通常会使用效果更好的方法


更新:你修复了你的标题,所以忽略其余的

现在,关于你的标题:关于LINQ,IEnumerable和IQueryable非常相似。它们都有几乎相同的扩展方法(Select、Where、Count等),主要(仅?)区别在于IEnumerable将
Func
作为参数,IQueryable将
Expression
作为参数。这两个表达式的表达方式相同(通常是lamba表达式),但在内部它们完全不同

IEnumerable是LINQ到对象的入口。LINQ to Objects扩展方法可以在任何IEnumerable(数组、列表、任何可以使用
foreach
迭代的对象)上调用,
Func
在编译时转换为IL,并在运行时像普通方法代码一样运行。请注意,其他一些LINQ提供程序使用IEnumerable,因此实际上在幕后使用LINQ到对象(LINQ到XML,LINQ到数据集)

IQueryable由LINQ到SQL、LINQ到E使用
var surveyNames = from s in db.Surveys select s.Name
IQueryable<string> surveryNames = db.Surveys.Select(s => s.Name);
Expression<Func<Survey, string>> selector = delegate(Survey s) { return s.Name; };
IQueryable<string> surveryNames = Queryable.Select(db.Surveys, selector);
var items = source.Where(s => s > 5);
var items = source.Where(s => s > 5);

if(smallerThanThen)
    items = items.Where(s => s < 10);
if(even)
    items = items.Where(s => (s % 2) == 0);

return items.OrderBy(s => s);
var floridaCount = source.Count(s => s.State == "FL");

var items = source
            .Where(s => s > 5)
            .Skip(5)
            .Take(3)
            .ToList();
var x = from s in db.Surveys
    join sq in db.Survey_Questions on s.ID equals sq.Survey_ID
    join q in db.Questions on sq.Question_ID equals q.ID
    join qg in db.Question_Groups on q.ID equals qg.Question_ID
    where s.Type_ID.Equals(typeID) & s.Type.Equals(type)
    select new { question = sq.Question, status = sq.Status, grp = qg };
var exp=x.Expression;