【问题标题】:VB not realising a collectionVB没有实现集合
【发布时间】:2015-05-14 10:36:47
【问题描述】:

我在我的 VB ASP.Net 项目中使用 linq 来填充搜索结果。使用 intersect 比较作为查询的单词列表和字符串。我在空格上拆分字符串以确保两个集合相交。但 VB 并没有意识到这一点并抛出以下错误。

An exception of type 'System.MissingMemberException' occurred in Microsoft.VisualBasic.dll but was not handled in user code

Additional information: Public member 'Count' on type 'String' not found.

select 语句中出现的代码如下

MatchCount = keywords.Intersect(IIf(IsNothing(t.TripName), t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName).ToLower().Split(" ")).Count() / IIf(IsNothing(t.TripName), t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName).Count

为它难以阅读的性质道歉,它在一个选择语句中,所以必须是一个查询。跨多行拆分它看起来像这样:

Dim name as string = IIf(IsNothing(t.TripName), t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName)
MatchCount = keywords.Intersect(name.ToLower().Split(" ")).Count()

编辑:- 完整的、原始的(不是我写的)选择语句

toReturn.AddRange(results.Select(Function(t) New SearchResult() _
                      With {
                            .MatchCount = keywords.Intersect(If(IsNothing(t.TripName), t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName).ToLower().Split(" ")).Count() / If(IsNothing(t.TripName), t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName).Count, _
                            .UID = t.TripID, _
                            .Title = IIf(t.TripName Is Nothing, t.tbl_Subject.SubjectName & " in " & t.tbl_City.CityName, t.TripName), _
                            .Description = t.DescriptionLong.ToString().Replace("<p>", "").Replace("</p>", "").Replace("<b>", "").Replace("</b>", "").Replace("<strong>", "").Replace("</strong>", "").Replace("<i>", "").Replace("</i>", "").Replace("<em>", "").Replace("</em>", "").Replace("<br>", "").Replace("<br />", ""), _
                            .ImageURL = IIf(t.ImageSub04 Is Nothing, t.tbl_City.ImageThumb, t.ImageSub04),
                            .URL = "/" & t.tbl_Subject.SubjectWebName & "/" & t.tbl_Country.CountryWebName & "/" & _
                                        IIf(t.TripWebName Is Nothing, _
                                        t.tbl_City.CityWebName, _
                                        t.TripWebName) _
                                        & "_trip/",
                            .IsCity = keywords.Contains(t.tbl_City.CityName) Or keywords.Contains(t.tbl_Country.CountryName)
                         }).OrderBy(Function(sr) sr.IsCity).ThenByDescending(Function(sr) sr.MatchCount))

【问题讨论】:

  • 字符串具有Length,而不是Count 属性。无论出于何种原因,keywords.Intersect 的结果都是一个字符串。 keywords的类型是什么,Intersect的定义是什么?您使用的是Enumerable.Intersect 还是您自己的版本?
  • 为什么不用多行多变量来存储值呢?那将更具可读性。也许您可以在没有 IIFs 的情况下将您的代码抽象为相关问题(您知道有一个 If-operator 吗?)。
  • Enumerable.Intersect,关键字是字符串列表。所以返回的类型应该总是可枚举的
  • 切换 Option Strict On 并将 IIf 更改为 If 开始。修复在那里抛出的任何错误可能会解决您的整体问题
  • @TimSchmelter +1 - 刚刚意识到那里隐藏着另一个Count()的调用

标签: c# asp.net .net vb.net linq


【解决方案1】:

既然您也在字符串上使用Count(),为什么不在那里使用Length

因为,正如我在问题中所说,它在一个选择语句中,所以我不能 存储变量

您甚至可以在查询中,例如使用匿名类型或(在查询语法中)使用 Let 关键字。

在这种情况下,我猜这就是你想要做的,看看它的可读性如何:

Dim sResults = From res In results
               Let longTripName = String.Format("{0} in {1}", res.tbl_Subject.SubjectName, res.TripName)
               Let trip = If(res.TripName, longTripName)
               Let tripWords = trip.ToLower().Split(" "c)
               Let matching = keywords.Intersect(tripWords).Count()
               Let matchCount = matching / trip.Length
               Let title = " this is your task "
               Let description = " this is your task "
               Let imageURL = " this is your task "
               Let url = " this is your task "
               Let isCity = True ' also your task '
               Select sr = New SearchResult With {
                   .MatchCount = matchCount,
                   .Title = title,
                   .Description = description,
                   .ImageURL = imageURL,
                   .URL = url,
                   .IsCity = isCity
               }
               Order By sr.IsCity, sr.MatchCount Descending
toReturn.AddRange(sResults)

但总的来说,我建议在 SearchResult 中实现一个适当的方法或构造函数,它封装了逻辑和复杂性。

此外,由于您使用的是 Split(" ") 并且可以编译,因此您应该真正更改为 Option Strict On。我猜你会得到很多编译器错误,这是一件好事,因为它向你展示了你必须解决的问题。在这里你必须使用Split(" "c)

【讨论】:

  • 再说一次,那没用。因为我的代码最初是在一个 select 语句中。生病将整个陈述添加到问题中
  • @LiamHT:再看看。在 VB.NET 中,您应该受益于更强大、更易读的查询语法。
  • @LiamHT 没有什么能阻止您在 select 语句中调用函数。只需将整个块提取到一个单独的函数中,该函数接受 t 的任何内容并返回 SearchResult,然后在 Select 的参数上调用它。 LINQ 甚至允许您将其称为results.Select(MyFactoryMethod),因为参数和结果是推断出来的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多