【问题标题】:VB to C# conversion incongruency with lambdasVB 到 C# 转换与 lambda 不一致
【发布时间】:2011-01-06 02:27:50
【问题描述】:

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

这里有一些背景:

OrderForm 是一个abstract 类,由Invoice(以及PurchaseOrder)继承。下面的 VB sn-p 工作正常:

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”,因为参数类型与委托参数类型不匹配

有什么方法可以在不重构我的整个代码库的情况下解决这个问题?

【问题讨论】:

  • 几乎所有 C# 都可以转换为 VB.NET,反之亦然,因为它都编译为 MSIL。你只需要找到表达问题的最佳点。这只是一个澄清性评论。
  • 对于将 VB 转换为 C# - 您是否考虑过反汇编 Redgate .NET Reflector 中已编译的 VB 函数(免费版工作正常),并将输出类型设置为 C#?可能有助于这些棘手的转化类型。

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


【解决方案1】:

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

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

从那里您可以很容易地看到您正在尝试将基类隐式转换为子类。人们在这里写的 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 冒昧地更正了答案中的错字:您在一个地方写了“选项显式”。我的建议是“始终开启 OPTION STRICT ON”,即使您正在编程 VB 而不是尝试转换为 C#!
  • 谢谢@MarkJ,我正在感冒,我的大脑有点冰冻
  • 谢谢你,但这并不能回答问题。 C# 代码是什么?
  • 对不起,我的意思是说@Anthony Pegram 有什么应该是正确的版本。我会在上面更新。
【解决方案2】:

好吧,Find 期待 Predicate&lt;OrderForm&gt;,但您正试图给它一个 Predicate&lt;Invoice&gt;。这不应该编译是正确的。我很惊讶 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
}

但是说真的,如果你在Invoices 之后,你为什么要把列表输入为List&lt;OrderForm&gt; 而不是List&lt;Invoice&gt;

【讨论】:

  • 我明白问题出在哪里......为什么它在 VB.NET 而不是 C# 中工作,我怎样才能让它在 C# 中工作?另外,我需要比较Invoice s,所以我不想拉OrderForm
  • VB(和一般的 BASIC)在历史上一直是一种“按我的意思做,而不是按我说的做”的语言类型。因此,这可能是编译器为您插入强制转换并更改废话以使您的生活更轻松的情况。虽然没有看到所有代码,但很难说。
  • 您还想看什么?我会告诉你任何你想让你更清楚的东西。
  • @Jason - 我的意思是 OP - mind if I call you "Bruce" to keep it clear?它在 VB 中工作,因为你有Option Strict Off。最好始终使用Option Strict On,然后VB.Net 编译器会警告您在哪里需要强制转换和转换。这就是 cdhowie 所暗示的。另见Chris's answer
【解决方案3】:

我猜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&lt;&gt; 中的 Find

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

【讨论】:

  • Invoice 派生自 OrderForm。那种工作,除了被比较的值(SubInvoiceNumber)特定于Invoice,所以省略显式类型不起作用:(
  • 如果您将FirstOrDefault() 更新为FirstOrDefault&lt;Invoice&gt;,这是正确的。
  • @Jason,你真的需要在FirstOrDefault 通话中使用&lt;Invoice&gt; 吗?您不需要,因为OfType 将导致IEnumerable&lt;Invoice&gt;,所以FirstOrDefault 不需要类型参数。如果您需要明确表达,那是出乎意料的。
【解决方案4】:

编辑:

其实不用新建列表

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

【讨论】:

    【解决方案5】:

    我猜你需要将OrderForm 转换为Invoice

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-24
      • 2011-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 1970-01-01
      相关资源
      最近更新 更多