Оптимизация компилятора анонимных типов

Хорошо хорошо я знаю, что это - взлом, но это было для крошечного проекта манипулирования данными, и я хотел играть вокруг.;-)

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

Так скажем, я хочу создать анонимный тип из некоторых введенных наборов данных, которые я имею:

var smallData1 = new smallData1().GetData().Select(
    x => new { Name = x.NAME, x.ADDRESS, City = x.CITY, State = x.STATE,
    Zip = x.ZIP, Country = x.COUNTRY, ManagerName = x.MANAGER_NAME,
    ManagerID = x.MANAGER_ID });

var smallData2 = new smallData2().GetData().Select(
    x => new { x.Name, x.ADDRESS, x.City, x.State, x.Zip, x.Country,
    x.ManagerName,x.ManagerID });

Я могу теперь сделать забавные вещи как smallData2. Кроме (smallData1); и т.д., и все это работает.

Теперь, что, если у меня есть большая пара анонимных типов:

var bigData1 = new BigAdapter1().GetData().Select(
    x => new { x.FirstName, x.LastName, x.Address, x.City, x.State,
    x.Zip, x.Country, x.Phone, x.Email, x.Website, x.Custom1, x.Custom2,
    x.Custom3, x.Custom4, x.Custom5, x.Custom6, x.Custom7, x.Custom8, x.Custom9,
    x.Custom10, x.Custom11, x.Custom12, x.Custom13, x.Custom14, x.Custom15,
    x.Custom16, x.Custom17, x.Custom18, x.Custom19, x.Custom20, x.Custom21,
    x.Custom22, x.Custom23, x.Custom24, x.Custom25, x.Custom26, x.Custom27,
    x.Custom28, x.Custom29});

var bigData2 = new BigAdapter2().GetData().Select(
    x => new { x.FirstName, x.LastName, x.Address, x.City, x.State, x.Zip,
    x.Country, x.Phone, x.Email, x.Website, x.Custom1, x.Custom2, x.Custom3,
    x.Custom4, x.Custom5, x.Custom6, x.Custom7, x.Custom8, x.Custom9, x.Custom10,
    x.Custom11, x.Custom12, x.Custom13, x.Custom14, x.Custom15, x.Custom16,
    x.Custom17, x.Custom18, x.Custom19, x.Custom20, x.Custom21, x.Custom22,
    x.Custom23, x.Custom24, x.Custom25, x.Custom26, x.Custom27,
    x.Custom28, x.Custom29});

Теперь, когда я делаю bigData2. Кроме (bigData1); компилятор жалуется:

Instance argument: cannot convert from
'System.Data.EnumerableRowCollection<AnonymousType#1>' to
'System.Linq.IQueryable<AnonymousType#2>'

Почему? Слишком много свойств, таким образом, компилятор решает, что это не стоит того для оптимизации?

Спасибо!

7
задан svick 6 March 2012 в 18:27
поделиться

3 ответа

Ага. Дело не в количестве свойств. Насколько вы уверены, что ваши адаптеры возвращают точно такие же типы данных?

2
ответ дан 7 December 2019 в 12:13
поделиться

Вы пробовали

bigData2.Except(bigData1.AsQueryable());

Я только что запустил пример LINQ с 40 свойствами и 20 000 000 строк, и я не столкнулся с проблемой.

(Попробуйте этот, к сожалению, не сворачиваемый пример в LINQPad)

void Main()
{
 Test t = new Test();
 var a = Enumerable.Range(1,10000000).Select(i => new  
 { 
  t.T0, t.T1, t.T2, t.T3, t.T4, t.T5, t.T6, t.T7, t.T8, t.T9,
  t.T10, t.T11, t.T12, t.T13, t.T14, t.T15, t.T16, t.T17, t.T18, t.T19,
  t.T20, t.T21, t.T22, t.T23, t.T24, t.T25, t.T26, t.T27, t.T28, t.T29,
  t.T30, t.T31, t.T32, t.T33, t.T34, t.T35, t.T36, t.T37, t.T38, t.T39,
 });

 Test2 t2 = new Test2();
 var b = Enumerable.Range(1,10000000).Select(i => new  
 { 
  t2.T0, t2.T1, t2.T2, t2.T3, t2.T4, t2.T5, t.T6, t2.T7, t2.T8, t2.T9,
  t2.T10, t2.T11, t2.T12, t2.T13, t2.T14, t2.T15, t2.T16, t2.T17, t2.T18, t2.T19,
  t2.T20, t2.T21, t2.T22, t2.T23, t2.T24, t2.T25, t2.T26, t2.T27, t2.T28, t2.T29,
  t2.T30, t2.T31, t2.T32, t2.T33, t2.T34, t2.T35, t2.T36, t2.T37, t2.T38, t2.T39,
 });

 a.Except(b).Dump();
}

class Test
{
 public string T0 { get; set ;}
 public string T1 { get; set ;}
 public string T2 { get; set ;}
 public string T3 { get; set ;}
 public string T4 { get; set ;}
 public string T5 { get; set ;}
 public string T6 { get; set ;}
 public string T7 { get; set ;}
 public string T8 { get; set ;}
 public string T9 { get; set ;}
 public string T10 { get; set ;}
 public string T11 { get; set ;}
 public string T12 { get; set ;}
 public string T13 { get; set ;}
 public string T14 { get; set ;}
 public string T15 { get; set ;}
 public string T16 { get; set ;}
 public string T17 { get; set ;}
 public string T18 { get; set ;}
 public string T19 { get; set ;}
 public string T20 { get; set ;}
 public string T21 { get; set ;}
 public string T22 { get; set ;}
 public string T23 { get; set ;}
 public string T24 { get; set ;}
 public string T25 { get; set ;}
 public string T26 { get; set ;}
 public string T27 { get; set ;}
 public string T28 { get; set ;}
 public string T29 { get; set ;}
 public string T30 { get; set ;}
 public string T31 { get; set ;}
 public string T32 { get; set ;}
 public string T33 { get; set ;}
 public string T34 { get; set ;}
 public string T35 { get; set ;}
 public string T36 { get; set ;}
 public string T37 { get; set ;}
 public string T38 { get; set ;}
 public string T39 { get; set ;}
}

class Test2
{
 public string T0 { get; set ;}
 public string T1 { get; set ;}
 public string T2 { get; set ;}
 public string T3 { get; set ;}
 public string T4 { get; set ;}
 public string T5 { get; set ;}
 public string T6 { get; set ;}
 public string T7 { get; set ;}
 public string T8 { get; set ;}
 public string T9 { get; set ;}
 public string T10 { get; set ;}
 public string T11 { get; set ;}
 public string T12 { get; set ;}
 public string T13 { get; set ;}
 public string T14 { get; set ;}
 public string T15 { get; set ;}
 public string T16 { get; set ;}
 public string T17 { get; set ;}
 public string T18 { get; set ;}
 public string T19 { get; set ;}
 public string T20 { get; set ;}
 public string T21 { get; set ;}
 public string T22 { get; set ;}
 public string T23 { get; set ;}
 public string T24 { get; set ;}
 public string T25 { get; set ;}
 public string T26 { get; set ;}
 public string T27 { get; set ;}
 public string T28 { get; set ;}
 public string T29 { get; set ;}
 public string T30 { get; set ;}
 public string T31 { get; set ;}
 public string T32 { get; set ;}
 public string T33 { get; set ;}
 public string T34 { get; set ;}
 public string T35 { get; set ;}
 public string T36 { get; set ;}
 public string T37 { get; set ;}
 public string T38 { get; set ;}
 public string T39 { get; set ;}
}
2
ответ дан 7 December 2019 в 12:13
поделиться

Анонимные типы, как и любые другие типы, привязаны к содержащей их сборке. Компилятор может считать их равными, только если два адаптера находятся в одной dll (фактически, в модуле IIRC).

Кроме этого, я бы проверил типы...

static Type Identify<T>(IEnumerable<T>) {return typeof(T);}
...
var t1= Identify(bigData1), t2= Identify(bigData2);
if(t1 == t2) {
    Console.WriteLine("they're the same");
} else {
    var props1 = t1.GetProperties(), props2 = t2.GetProperties();
    if(props1.Length != props2.Length) {
        Console.WriteLine(props1.Length + " vs " + props2.Length);
    } else {
        Array.Sort(props1, p => p.Name);
        Array.Sort(props2, p => p.Name);
        for(int i = 0 ; i < props1.Length ; i++) {
            if(props1[i].Name != props2[i].Name)
                Console.WriteLine(props1[i].Name + " vs " + props2[i].Name);
            if(props1[i].PropertyType != props2[i].PropertyType)
                Console.WriteLine(props1[i].PropertyType + " vs " + props2[i].PropertyType );
        }
    }
}
1
ответ дан 7 December 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: