Я пытаюсь использовать Linq для преобразования списка в словарь. Я смог получить правильные результаты с анонимными типами в качестве ключей, но не с конкретными типами. Пожалуйста, см коды отрезали ниже:Linq ToDictionary anonymous verses конкретных типов
// Works. Produces 329 entries in dictionary, as expected.
var groupByMonth =
from e in list
group e by new { e.chk.Month, e.chk.Year } into g
select new { month = g.Key, rates = g.ToList() };
var monnthlyRates = groupByMonth.ToList();
var monnthlyRatesDict = groupByMonth.ToDictionary(t => t.month, t => t.rates);
// IS NOT WORKING. Produces 30K entries in dictionary; same num as in the list.
// i.e. the grouping does not happen
var groupByMonth2 =
from e in list
group e by new MonthYear { Month = e.chk.Month, Year = e.chk.Year } into g
select new MonthYearRates { MonthYear = g.Key, Rates = g.ToList()};
var monnthlyRatesDict2 = groupByMonth2.ToDictionary(t => t.MonthYear, t => t.Rates);
// Works. Dictionary has 329 entries
var groupByMonth3 =
from e in list
group e by new DateTime(e.chk.Year, e.chk.Month, 1) into g
select new MonthYearRates2 { MonthYear = g.Key, Rates = g.ToList() };
var monnthlyRatesDict3 = groupByMonth3.ToDictionary(t => t.MonthYear, t => t.Rates);
Я попытался решить эту проблему путем внедрения IComparer и/или IComparable в конкретном типе; безрезультатно
class MonthYear : IComparer
// class MonthYear : IComparable, IComparer
{
public MonthYear()
{
}
public MonthYear(int month, int year)
{
Month = month;
Year = year;
}
int IComparer.Compare(Object x, Object y)
{
MonthYear xo = (MonthYear)x;
MonthYear yo = (MonthYear)y;
if (yo.Year > xo.Year)
return 1;
else if (yo.Year < xo.Year)
return -1;
else
{
if (yo.Month > xo.Month)
return 1;
else if (yo.Month < xo.Month)
return -1;
else
return 0;
}
}
//int IComparable.CompareTo(object obj)
//{
// MonthYear o = (MonthYear)obj;
// if (Year > o.Year)
// return 1;
// else if (Year < o.Year)
// return -1;
// else
// {
// if (Month > o.Month)
// return 1;
// else if (Month < o.Month)
// return -1;
// else
// return 0;
// }
//}
public int Month;
public int Year;
}
Я понимаю, что Lookup лучше подходит для этого словаря; Я буду искать Lookup, как только я закончил с любыми анонимными типами.
Анонимные типы используют структурное равенство, которое посредством отражения проверяет все свойства типа, конкретные классы используют объект/ссылку равенство по умолчанию. Создайте собственный класс, который реализует тип 'IEqualityComparer'. то есть не IComparer и как отдельный класс. Ie 'class MonthYearEqualityComparer: IEqualityComparer {...}' и передать это методу 'ToDictionary' в качестве последнего параметра –
pinkfloydx33
Альтернативно, если вы можете сделать MonthYear неизменной' struct' вместо этого, вы получите структурное равенство без какой-либо работы над ваша часть (опять же, сделанная по умолчанию с использованием отражения), хотя это не может быть жизнеспособным вариантом. – pinkfloydx33