Vb.net 为什么在将.toList添加到linq查询的末尾时只能访问匿名类型的属性
我正在学习LINQ和VB,只花了一个小时试图访问LINQ查询中定义的匿名类型的字段。我学到的关键是在尝试使用for循环迭代查询之前,将查询转换为列表。 此操作不起作用:编辑(此操作可编译,但intellisense无法识别该类型) 但这确实:Vb.net 为什么在将.toList添加到linq查询的末尾时只能访问匿名类型的属性,vb.net,linq,anonymous-types,Vb.net,Linq,Anonymous Types,我正在学习LINQ和VB,只花了一个小时试图访问LINQ查询中定义的匿名类型的字段。我学到的关键是在尝试使用for循环迭代查询之前,将查询转换为列表。 此操作不起作用:编辑(此操作可编译,但intellisense无法识别该类型) 但这确实: Dim varbl=(from itm in collct select New With {.n=itm.Name}).toList for each returnedItem in varbl returnedItem.n 'this w
Dim varbl=(from itm in collct select New With {.n=itm.Name}).toList
for each returnedItem in varbl
returnedItem.n 'this works
next
有人能解释一下发生了什么事吗?上面的帖子(其他方面也很有用!)只是说“因为编译器的工作方式,一旦创建了列表,下面的内容也应该可以工作,因为匿名类型具有相同的结构,所以它们也是相同的类型。我手头没有编译器来验证这一点”好吧,我不打算回答,因为我的VB已经非常生锈,而且已经过时了(呃,大约十年前的VB6)。但是,从.NET的角度来看,这里确实出现了一些问题 你对你链接到的答案的阅读(IMO的解释不完整)是错误的。这并不是说你需要把匿名对象放到一个列表中,而是那里的查询已经把它放到了一个
列表中,这意味着编译器无法分辨它有什么属性(它处理的是对象
不是所讨论的匿名类型的对象,并且对象
没有选中的属性)
不管怎样,我试着把你最初的尝试写进一些C#as:
然后我在reflector中编译并反编译为VB.NET,它将我的Main
作为:
Public Shared Sub Main()
Dim collct As TestType() = New TestType() { New TestType("abc"), New TestType("def"), New TestType("xyz") }
Dim varbl = (From itm In collct Select New With { _
.n = itm.Name _
})
Dim returnedItem
For Each returnedItem In varbl
Console.WriteLine(returnedItem.n)
Next
End Sub
看起来很像你的原作,不是吗
好吧,它工作了;它编译并运行,给了我正确的答案
我能想到的唯一一件事是,IntelliSense可能在这里不太合适。我发现,在过去的一些时候,IntelliSense很难建议匿名类型的属性名称,而我使用SharpDevelop来编写C#而不是VB(在您使用的任何IDE中),这里可能就是这种情况-您实际上一直都有正确的代码,但IntelliSense没有意识到这一点
归根结底,IntelliSense非常好,但它不是编译器,而且它不能像编译器那样花费太多的资源来做事情,因为在我们打字时,它可能会减慢我们的速度
顺便说一句,除非您确实需要一个列表,否则您不应该调用ToList
。想象一下,如果collct
是一个按需加载的枚举,从数据库或文件加载内容后,它将返回数千个对象
如果您不调用ToList
,那么在第一个数据到达后,您将立即开始遍历它们,并且一次只需要使用少量内存
若您确实调用了ToList
,那个么程序将停留在该行,直到它将每个对象加载到内存中的一个大列表中,然后才为每个启动
当然,有时您确实需要能够在列表中前后移动,或者在迭代之前知道计数,然后调用ToList
当然比不断重复每个的要好,但是如果您不知道您需要它,就不要使用它。这并不能回答您的问题,但如果您需要的话刚开始,我强烈建议你学习C#,而不是VB。你会找到更多的示例代码和文章来帮助你。我不知道@olivehour似乎世界上所有的代码都是C#,除了在网上某个地方写教程的家伙,关于我想知道的事情:)嗨,Jon。谢谢你的回答。我删除了.toList,代码编译后运行良好。我认为你是对的:在这种情况下,intellisense没有编译器那么聪明。只是b/c intelsense不能识别类型,并不意味着编译器也不能识别类型。显然(您可能知道)在C#中,Var关键字包含一个变量,在编译代码之前,该变量的类型不会被赋值。我猜VB的Dim也是这样工作的。也许会添加toList“预先指定”的类型?无论如何,对于noob来说,关键是intellsense不是编译器,一个比一些“有经验”的用户做得更好的“noob”。即使是真正有经验的用户(多年的经验,而不是一年的几次经验)也会发现IntelliSense突然没有发现什么东西时令人不安。不过,编译器键入了变量(var
in C#,Dim
不带As
和带选项推断on
)通常由IntelliSense接收。它只是偶尔不起作用,或者不完全起作用。
private class TestType
{
public string Name{get;set;}
public TestType(string name)
{
this.Name = name;
}
}
public static void Main()
{
TestType[] collct = new TestType[]{new TestType("abc"), new TestType("def"), new TestType("xyz")};
var varbl = from itm in collct select new {n = itm.Name};
foreach(var returnedItem in varbl)
Console.WriteLine(returnedItem.n);
}
Public Shared Sub Main()
Dim collct As TestType() = New TestType() { New TestType("abc"), New TestType("def"), New TestType("xyz") }
Dim varbl = (From itm In collct Select New With { _
.n = itm.Name _
})
Dim returnedItem
For Each returnedItem In varbl
Console.WriteLine(returnedItem.n)
Next
End Sub