VB.NET中BindingList类型转换与If表达式类型推断错误求助
解决VB.NET开发中的两个类型错误
错误1:类型转换失败
报错信息:无法将类型为System.Collections.Generic.List1[VB$AnonymousType_15`7[System.String,System.String,System.String,System.Object,System.Object,System.Object,System.String]]`的对象转换为`System.Collections.Generic.IList`1[ItemCards2]`
报错代码行:
bindingSource = New BindingSource With {.DataSource = New BindingList(Of ItemCards2)(CType(Cardex.ToList(), IList(Of ItemCards2)))}
问题原因
Linq查询的Select语句返回的是匿名类型集合,而非ItemCards2类型的实例集合。直接将匿名类型列表强制转换为IList(Of ItemCards2)会因类型不匹配导致转换失败。
修复方案
在Linq的Select子句中,直接创建ItemCards2的实例,替代生成匿名类型:
Select New ItemCards2 With { .ITEM = ITEM, .PRODUCTIONNAME = PRODUCTIONNAME, .BRAND = BRAND, .PIQ = If(PIQ <> 0, PIQ, 0), .SIQ = If(SIQ <> 0, SIQ, 0), .BLC = If(BLC <> 0, BLC, 0), .STATUS = STATUS }
错误2:类型推断错误
报错信息:无法推断通用类型,因为存在多种可能类型
报错代码行:
PIQ = If(PIQ <> CInt("0"), PIQ, ""), SIQ = If(SIQ <> CInt("0"), SIQ, ""), BLC = If(BLC <> CInt("0"), BLC, ""),
问题原因
If语句的两个分支返回值类型不一致:第一个分支返回Integer类型(PIQ/SIQ/BLC的数值),第二个分支返回String类型(空字符串"")。VB.NET编译器无法确定最终返回类型,因此报错。同时,ItemCards2类中PIQ、SIQ、BLC的属性类型为Integer,本身也不能接受字符串值,即使编译通过也会引发运行时错误。
修复方案
保持类型一致,将空字符串替换为0(匹配属性的Integer类型)。如果需要在界面上显示空值,不要修改数据类型,可通过DataGridView的单元格格式设置实现:
PIQ = If(PIQ <> 0, PIQ, 0), SIQ = If(SIQ <> 0, SIQ, 0), BLC = If(BLC <> 0, BLC, 0),
完整修正代码
Public Class Form2 Private bindingSource As BindingSource = Nothing Private MasterItem, PurchaseDetails, SalesDetails As New List(Of ItemCards2) Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load LoadLINQ() End Sub Private Function CreateConnection() As String Return ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TRIAL2.accdb;Persist Security Info=False;") End Function Private Sub LoadLINQ() Const Qry_MST = "SELECT * FROM MASTERITEM" Const Qry_PI = "SELECT a.ITEM, '' AS PRODUCTIONNAME, '' AS BRAND, 0 AS LSQ, 0 AS TPIQ, a.QTY AS PIQ, 0 AS TSIQ, 0 AS SIQ, 0 AS TRSQ, 0 AS RSQ, 0 AS TRPQ, 0 AS RPQ, 0 AS BLC FROM (PurchaseDetails a INNER JOIN" & " Purchase b ON a.INVONO = b.INVONO) INNER JOIN" & " CUSTCODE c On b.CUSTCODE = c.CUSTCODE" & " WHERE b.DATEINVO >= CDate('01/01/2024')" & " AND c.GROUP IS NULL" Const Qry_SI = "SELECT a.ITEM, '' AS PRODUCTIONNAME, '' AS BRAND, 0 AS LSQ, 0 AS TPIQ, 0 AS PIQ, 0 AS TSIQ, a.QTY AS SIQ, 0 AS TRSQ, 0 AS RSQ, 0 AS TRPQ, 0 AS RPQ, 0 AS BLC FROM (SalesDetails a INNER JOIN" & " Sales b ON a.INVONO = b.INVONO) INNER JOIN" & " CUSTCODE c ON b.CUSTCODE = c.CUSTCODE" & " WHERE b.DATEINVO >= CDATE('01/01/2024')" & " AND c.GROUP IS NULL" Using Connection = New OleDbConnection(CreateConnection()) With Connection MasterItem = CType(Connection.Query(Of ItemCards2)(Qry_MST), List(Of ItemCards2)) PurchaseDetails = CType(Connection.Query(Of ItemCards2)(Qry_PI), List(Of ItemCards2)) SalesDetails = CType(Connection.Query(Of ItemCards2)(Qry_SI), List(Of ItemCards2)) End With End Using Dim Cardex = From card In PurchaseDetails.Union(SalesDetails) Join mst In MasterItem On card.ITEM Equals mst.ITEM Group card By card.ITEM, mst.PRODUCTIONNAME, mst.BRAND Into Group Let PIQ = (From x In Group Select x.PIQ).Sum Let SIQ = (From x In Group Select x.SIQ).Sum Let BLC = (PIQ) - (SIQ) Let STATUS = If(BLC < 24, "NEED TO PRODUCE", "") Select New ItemCards2 With { .ITEM = ITEM, .PRODUCTIONNAME = PRODUCTIONNAME, .BRAND = BRAND, .PIQ = If(PIQ <> 0, PIQ, 0), .SIQ = If(SIQ <> 0, SIQ, 0), .BLC = If(BLC <> 0, BLC, 0), .STATUS = STATUS } Order By ITEM bindingSource = New BindingSource With {.DataSource = New BindingList(Of ItemCards2)(Cardex.ToList())} DataGridView1.DataSource = bindingSource End Sub End Class Public Class ItemCards2 Public Property ITEM() As String Public Property PRODUCTIONNAME As String Public Property BRAND As String Public Property PIQ As Integer Public Property SIQ As Integer Public Property BLC As Integer Public Property STATUS As String End Class
内容的提问来源于stack exchange,提问作者user22579796
相关产品推荐
相关产品推荐

