Несоответствие преобразования VB в C # с лямбдами - PullRequest
3 голосов
/ 06 января 2011

У меня есть немного кода, который мне поручено преобразовать в C # из VB. Мне кажется, что мой фрагмент не может быть преобразован из одного в другой, и если это так, я просто не знаю, как это сделать, и я немного расстроен.

Вот немного фона:

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);

Однако при этом я получаю следующую ошибку:

Невозможно преобразовать лямбда-выражение в тип делегата 'System.Predicate', поскольку типы параметров не соответствуют типам параметров делегата

Есть ли способ исправить это без реструктуризации всей моей кодовой базы?

Ответы [ 5 ]

5 голосов
/ 06 января 2011

Всякий раз, когда вы конвертируете VB в C #, ВСЕГДА ВКЛЮЧИТЕ СТРОИТЕЛЬСТВО ОПЦИИ .В этом случае вы увидите сообщение об ошибке еще до того, как нажмете c #.В этом случае VB вернет

Опция Strict On не позволяет сужать неявные преобразования типов между лямбда-выражением и делегатом 'System.Predicate (Of OrderForm)'

Отсюда довольно легко увидеть, что вы пытаетесь неявно привести базовый класс в качестве дочернего класса.Код C #, который люди здесь написали, является правильным, вот эквивалент VB:

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

ОБНОВЛЕНИЕ

Вот версия C # из сообщения @Anthony Pegram:

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

Кроме того, я рекомендую вам внести некоторые изменения в ваш шаблон, если это возможно.GetForms() сейчас возвращает OrderForms, но позже вы просто предполагаете, что все они Invoices.Надеюсь, у вас есть логика, чтобы проверить это.Я бы порекомендовал, чтобы GetForms() действительно возвращал Invoices в противном случае.

3 голосов
/ 06 января 2011

Ну, 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 голосов
/ 06 января 2011

Я предполагаю, что OrderForm происходит от Invoice. Если это так, перепишите вашу лямбду, чтобы пропустить явное объявление типа внутри Find. (Не могу с уверенностью сказать, что для VB, но для C # тип не требуется в лямбда-выражении, он будет выведен.)

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

Редактировать

Исходя из вашего комментария, вам нужно будет выполнить кастинг внутри лямбды, а также получить результат.

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);
1 голос
/ 06 января 2011

Редактировать:

На самом деле вам не нужно создавать новый список

List<OrderForm> Invs = new List<OrderForm> { new Invoice(1), new Invoice(2) };  
List<Invoice> invoices = Invs.OfType<Invoice>().Where(invoice => invoice.val == 1).ToList();
0 голосов
/ 06 января 2011

Полагаю, вам нужно наложить OrderForm на Invoice:

Invoice inv = (Invoice)Invs.Find(
    someInv => thePO.SubPONumber == ((Invoice)someInv).SubInvoiceNumber); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...