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

发布于 2024-10-10 17:43:40 字数 805 浏览 0 评论 0原文

我有一些代码,我的任务是将 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”,因为参数类型与委托参数类型不匹配

有没有办法在不重构整个代码库的情况下解决此问题?

I have a bit of code that I have been tasked with converting to C# from VB. A snippet of mine seems like it cannot be converted from one to the other, and if so, I just don't know how to do it and am getting a little frustrated.

Here's some background:

OrderForm is an abstract class, inherited by Invoice (and also PurchaseOrder). The following VB snippet works correctly:

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

In C#, the best I came to converting this is:

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

However, I get the following error when I do this:

Cannot convert lambda expression to delegate type 'System.Predicate' because the parameter types do not match the delegate parameter types

Is there any way to fix this without restructuring my whole codebase?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

妥活 2024-10-17 17:43:40

每当您将 VB 转换为 C# 时,始终打开 OPTION STRICT ON。在这种情况下,您甚至在点击 c# 之前就会看到错误消息。在这种情况下VB将返回

Option Strict On 不允许
隐式类型转换的缩小
lambda 表达式和之间
委托'System.Predicate(Of
订单表格)'

从那里您可以很容易地看到您正在尝试将基类隐式转换为子类。人们在这里编写的 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 否则。

Whenever you convert VB to C#, ALWAYS TURN OPTION STRICT ON. In this case you'll see the error message before you even hit c#. In this case VB will return

Option Strict On does not allow
narrowing in implicit type conversions
between the lambda expression and
delegate 'System.Predicate(Of
OrderForm)'

From there you can pretty easily see that you're trying to implicitly cast a base class as a child class. The C# code that people wrote here is correct, here's the VB equivalent:

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

UPDATE

Here's the C# version from @Anthony Pegram's post:

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

Also, I recommend that you make some changes to your pattern if possible. GetForms() right now returns OrderForms but later you just assume that they're all Invoices. Hopefully you've got some logic to verify that. I'd recommend that GetForms() actually returns Invoices otherwise.

君勿笑 2024-10-17 17:43:40

好吧,Find 需要一个 Predicate,但您试图给它一个 Predicate。这是正确的,这不应该编译。我对 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

Well, Find is expecting a Predicate<OrderForm> but you are trying to give it a Predicate<Invoice>. It is correct that this should not compile. I'm surprised the VB.NET works.

What is thePO?

Additionally, the result of Find is an OrderForm and you are assigning to a variable of type Invoice.

Ideally, you want something like this:

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

If you want to pull invoices, you could do something like this:

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

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

But really, if you are after Invoices, why are you typing the list as List<OrderForm> instead of List<Invoice>?

无戏配角 2024-10-17 17:43:40

我猜测 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 扩展方法,而不是在 List 中查找Find

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

I'm guessing that OrderForm derives from Invoice. If so, rewrite your lambda to omit the explicit type declaration inside the Find. (Can't say with certainty for VB, but for C#, the type is not required in a lambda, it will be inferred.)

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

Edit

Based on your comment, you're going to have to do some casting inside the lambda and also to the result.

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

Or you could elect to use LINQ extension methods as opposed to Find in List<>

Invoice inv = Invs.OfType<Invoice>().FirstOrDefault<Invoice>(someInv => someInv.SubInvoiceNumber == thePO.SubPONumber);
蒲公英的约定 2024-10-17 17:43:40

编辑:

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

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

Edit:

Actually, you don't need to create a new list

List<OrderForm> Invs = new List<OrderForm> { new Invoice(1), new Invoice(2) };  
List<Invoice> invoices = Invs.OfType<Invoice>().Where(invoice => invoice.val == 1).ToList();
又怨 2024-10-17 17:43:40

我的猜测是,您需要将 OrderForm 转换为 Invoice

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

My guess is that you need to cast your OrderForm to an Invoice:

Invoice inv = (Invoice)Invs.Find(
    someInv => thePO.SubPONumber == ((Invoice)someInv).SubInvoiceNumber); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文