VB与C#的转换与lambda不一致

时间:2011-01-06 02:27:50

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

我有一些代码,我的任务是从VB转换为C#。我的片段似乎无法从一个转换为另一个,如果是这样,我只是不知道该怎么做而且有点沮丧。

以下是一些背景知识:

OrderFormabstract类,由Invoice(以及PurchaseOrder)继承。以下VB代码段正常工作:

Dim Invs As List(Of OrderForm) = GetForms(theOrder.OrderID)
....
Dim inv As Invoice = Invs.Find(
    Function(someInv As Invoice) thePO.SubPONumber = someInv.SubInvoiceNumber)

在C#中,我最好转换它:

List<OrderForm> Invs = GetForms(theOrder.OrderID);
....
Invoice inv = Invs.Find(
    (Invoice someInv) => thePO.SubPONumber == someInv.SubInvoiceNumber);

但是,当我这样做时,我收到以下错误:

  

无法将lambda表达式转换为委托类型'System.Predicate',因为参数类型与委托参数类型不匹配

有没有办法解决这个问题而不重构整个代码库?

5 个答案:

答案 0 :(得分:5)

每当您将VB转换为C#时,始终选择OPTR STRICT ON 。在这种情况下,您甚至可以在点击c#之前看到错误消息。在这种情况下,VB将返回

  

Option Strict On不允许   缩小隐式类型转换   在lambda表达式和   委托'System.Predicate(Of   OrderForm)'

从那里你可以很容易地看到你试图隐含地将基类强制转换为子类。人们在这里写的C#代码是正确的,这是VB的等价物:

Dim inv As Invoice = DirectCast(Invs.Find(Function(someInv As OrderForm) SubPONumber = DirectCast(thePO.SubPONumber, Invoice).SubInvoiceNumber), Invoice)

<强>更新

这是@Anthony Pegram的帖子中的C#版本:

Invoice inv = (Invoice)Invs.Find(someInv => thePO.SubPONumber == ((Invoice)someInv).SubInvoiceNumber);

此外,如果可能,我建议您对模式进行一些更改。 GetForms()现在返回OrderForms,但稍后你会假设它们都是Invoices。希望你有一些逻辑来验证。我建议GetForms()实际上返回Invoices

答案 1 :(得分:3)

好吧,Find期待Predicate<OrderForm>,但您正试图给它Predicate<Invoice>。这不应该编译是正确的。我对VB.NET的工作感到惊讶。

什么是thePO

此外,Find的结果是OrderForm,您将分配给Invoice类型的变量。

理想情况下,你需要这样的东西:

OrderForm orderForm = Invs.Find(o => o.SomeOrderFormProperty == someValue);

如果您想提取发票,可以执行以下操作:

Invoice invoice = Invs.OfType<Invoice>()
                      .SingleOrDefault(x => x.SomeInvoiceProperty == someValue);

if(invoice != null) {
    // do something
}

但实际上,如果您在Invoice之后,为什么要将列表键入为List<OrderForm>而不是List<Invoice>

答案 2 :(得分:2)

我猜测OrderForm来自Invoice。如果是这样,请重写lambda以省略Find中的显式类型声明。 (不能肯定地说VB,但对于C#,lambda中不需要类型,它将被推断。)

Invoice inv = Invs.Find(someInv => thePO.SubPONumber == someInv.SubInvoiceNumber); 

修改

根据你的评论,你将不得不在lambda内部进行一些投射,也需要在结果中进行投射。

Invoice inv = (Invoice)Invs.Find(someInv => 
                   thePO.SubPONumber == ((Invoice)someInv).SubInvoiceNumber);  

或者你可以选择使用LINQ扩展方法而不是Find中的List<>

Invoice inv = Invs.OfType<Invoice>().FirstOrDefault<Invoice>(someInv => someInv.SubInvoiceNumber == thePO.SubPONumber);

答案 3 :(得分:1)

编辑:

实际上,您不需要创建新列表

List<OrderForm> Invs = new List<OrderForm> { new Invoice(1), new Invoice(2) };  
List<Invoice> invoices = Invs.OfType<Invoice>().Where(invoice => invoice.val == 1).ToList();

答案 4 :(得分:0)

我猜您需要将OrderForm投放到Invoice

Invoice inv = (Invoice)Invs.Find(
    someInv => thePO.SubPONumber == ((Invoice)someInv).SubInvoiceNumber); 
相关问题