LINQ查询具有匿名类型和用户定义类型

本文关键字:类型 用户 定义 查询 LINQ | 更新日期: 2023-09-27 18:11:51

匿名类在c#中具有只读属性。它通常用于在linq中声明选择查询以从数据库中获取特定值。在我的代码中,我有以下查询。用new语句选择匿名类的新对象让我很困惑。我有一个StudentClerkshipsLogModel的模范班。当我使用模型名称时,查询结果允许编辑。

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
             where entity.StudentID == intStudentID                             
             select new StudentClerkshipsLogModel
             {
                 StudentClerkshipID = entity.StudentClerkshipID,
                 StudentID = entity.StudentID,
                 ClerkshipID = entity.ClerkshipID,
             }).ToList();

当我在select语句中没有提到new后的类型时,我无法退出。编译器抛出错误。匿名对象是只读的。

var query = (from entity in _tblStudentClerkshipsLog.GetQueryable()
             where entity.StudentID == intStudentID                             
             select new 
             {
                 StudentClerkshipID = entity.StudentClerkshipID,
                 StudentID = entity.StudentID,
                 ClerkshipID = entity.ClerkshipID,
             }).ToList()

我的问题是linq如何绑定关于两个查询不同。两个查询都有动态绑定,或者第一个是静态绑定。

LINQ查询具有匿名类型和用户定义类型

你得到的错误真的与LINQ没有任何关系。不使用LINQ也可以看到同样的结果:

var anonymous = new { Name = "Fred" };
anonymous.Name = "Joe"; // Error, as properties of anonymous types are read-only

所以如果你想修改你的LINQ查询获取的对象,你不应该使用匿名类型。但是这两个LINQ查询都是静态绑定的——匿名类型在编译时仍然是完全已知的,编译器对它们应用正常的类型限制。例如:

var anonymous = new { Name = "Fred" };
Console.WriteLine(anonymous.Foo); // Error: no property Foo
int bar = anonymous.Name; // Error: no conversion from string to int

如果我正确理解你,你想知道,LINQ提供程序如何设置匿名对象的属性,因为它们是"真正的"只读属性(没有任何private set,但get只有)?

当您调用IQueryable<T>Select扩展方法时,它接受类型为Expression<Func<T, TResult>表达式。如果您要为Select编写一些存根,您可以使用debugger查看生成的表达式:

public static class MyExtensions
{
    public static void MySelect<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> projection)
    {
        System.Diagnostics.Debug.WriteLine(projection);
    }
}

区别在于编译器如何为命名类型和匿名类型生成lambda表达式。当您为命名类型调用Select时,表达式将如下所示:

{_ => new Person() {Id = _.Id, Name = _.Name}}

即首先构造新的Person对象,然后初始化成员(MemberInit表达式)。

但是当你调用匿名类型Select时,表达式将被构建为构造函数调用(New表达式):

{_ => new <>f__AnonymousType0`2(a = _.Id, b = _.Name)}

LINQ提供程序在具体化查询结果时将这些lambda编译为委托,并最终调用匿名类型的构造函数。

我发现LINQ结果与匿名类型结果有以下差异

  1. 结果是不可编辑的,例如,如果我们赋值给gridview它

  2. 匿名对象的作用域问题。我们不能传递类型到另一个方法。定义var类型的形参;Var必须总是

如果您只需要在当前上下文中用于只读目的的结果,请使用匿名查询。如果在其他函数中需要结果,则必须定义对象的类型。new之后的对象类型将使用您想要从结果定义中获得的属性创建,然后在花括号{}中创建。没有必要初始化模型类的所有值