Вы писали:
предметы облагаются разными налогами, но в основном предметы облагаются одинаковыми налогами
Самое важное для вас - определить, когда два налогаравны.Это когда они равны TaxId
и TaxValue
, или когда они имеют одинаковые TaxValue
, или это должен быть один и тот же объект.Итак, какие из этих пяти налогов равны:
Taxes a = new Taxes {Taxid = 1, TaxValue = 3};
Taxes b = new Taxes {Taxid = 1, TaxValue = 4};
Taxes c = new Taxes {Taxid = 2, TaxValue = 4};
Taxes d = new Taxes {Taxid = 2, TaxValue = 4};
Taxes e = d;
Если ваш ответ будет: это зависит: иногда только d == e (тот же объект), иногда b == c == d == e (равный TaxValue), то вы должны предоставить средство сравнения равенства: объект, который реализует IEqualityComparer<Taxes>
.
Обычно ответ не так сложен, я думаю, вы хотите сказать, что два налога равны, если ониимеют равное TaxValue
Итак, ваши требования следующие:
- Ввод: последовательность OrderDetails.Каждый OrderDetail имеет DetailId и последовательность из нуля или более налогов.Каждый налог имеет TaxId и TaxValue.
- Два налога считаются равными, если они имеют одинаковое TaxValue.
- Запрошенный вывод: Из каждого OrderDetail DetailId и последовательности всех его уникальных налогов.
Чтобы выбрать свойства элементов ввода, используйте Enumerable.Select Для сохранениятолько уникальные выходные значения последовательности используют Enumerable.Distinct
var result = myOrderDetails // take my sequence of OrderDetails
.Select(orderDetail => new // from every orderDetail in this sequence make one new object
{ // with the following properties
DetailId = orderDetail.DetailId,
TaxValues = orderDetail.Taxes // from all Taxes of this orderDetail,
.Select(tax => tax.TaxValue) // select only the TaxValues
.Distinct(), // and remove duplicates
// or if two taxValues are equal if they are the same object:
Taxes = orderDatail.Taxes // from all Taxes of this orderDetail
.Distinct() // remove duplicates
.Select(tax => tax.TaxValue), // and keep only the TaxValue (optional)
});
Если ваша идея о равенстве налогов не является такой простой, например, если вы определите равенство как:
Два налога равны, если они имеют одинаковый TaxId и равны TaxValue
В этом случае вам придется написать средство сравнения на равенство.Они не очень сложны, однако вы должны иметь в виду кое-что:
- Что делать с нулевым значением?Если оба значения равны нулю, равны ли они?
- Имейте в виду, что производный класс TaxValue обычно не равен самому TaxValue
Рассмотрите возможность чтения Определите равенство значенийдля типа
class TaxesEqualityComparer : EqualityComparer<TaxValue>
{
public static readonly IEqualityComparer<TaxValue> ValueComparer
= new TaxesEqualityComparer()
public override bool Equals(TaxValue x, TaxValue y)
{
// the following lines are almost always the same:
if (x == null) return y == null; // true if both null
if (y != null) return false; // because x not null and y is null
if (Object.ReferenceEquals(x, y) return true; // optimalization: same object
// no need to check the properties
if (x.GetType() != y.GetType()) return false; // not same type
// here start the differences of default Taxes comparison
// when would you say that two Taxes are equal?
return x.TaxId == y.TaxId
&& x.TaxValue == y.TaxValue;
};
public override int GetHashCode(x)
{
...
}
}
GetHashCode - это оптимизация, используемая такими классами, как словари, наборы, и функциями, такими как Distinct (), для быстрого поиска неравенств.Не существует «лучшего» способа определить эту функцию. Переполнение стека: лучший алгоритм для GetHashCode может помочь вам.
После того, как вы определили класс, вы можете использовать равный компаратор в Distinct:
// use default equality (= equal if same object)
...
.Distinct(TaxesEqualityComparer.Default)
// use your own definition of Taxes equality:
...
.Distinct(TaxesEqualityComparer.ValueComparer)