我有一些代码,我的任务是从VB转换为C#。我的片段似乎无法从一个转换为另一个,如果是这样,我只是不知道该怎么做而且有点沮丧。
以下是一些背景知识:
OrderForm
是abstract
类,由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',因为参数类型与委托参数类型不匹配
有没有办法解决这个问题而不重构整个代码库?
答案 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);