2010-07-23 19 views
7

OK OK, so che questo è un hack, ma questo era per un piccolo progetto di manipolazione dei dati e volevo giocare. ;-)Ottimizzazioni del compilatore di tipi anonimi

Ho sempre avuto l'impressione che il compilatore avrebbe esaminato tutti i tipi anonimi utilizzati in un programma C# e se le proprietà fossero le stesse, creerebbe solo una classe dietro le quinte.

Quindi diciamo che voglio creare un tipo anonimo di alcuni dataset tipizzati che ho:

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

ora posso fare cose divertenti come smallData2.Except (smallData1); ecc. E tutto funziona.

Ora, che cosa se ho una coppia più alta di tipi anonimi:

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

Ora, quando faccio bigData2.Except (bigData1); il compilatore si lamenta:

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

Perché? Troppe proprietà, quindi il compilatore decide che non vale la pena di ottimizzare?

Grazie!

risposta

2

Yep. Non è il numero di proprietà. Sei sicuro che i tuoi adattatori stanno restituendo esattamente gli stessi tipi di dati?

+0

Sì, gli adattatori stanno restituendo tipi di dati leggermente diversi, ma la differenza è solo il tipo di set di dati tipizzati (provengono da database diversi). Tutte le proprietà sono stringhe, motivo per cui ho pensato di utilizzare solo un tipo anonimo e che mi permettesse di trattare i dati come UN tipo di tipo anziché due. – Pandincus

+0

OMG DOVE HA FATTO DOPPIO DOPPIO. Err ... okay, avevi completamente ragione. Uno dei tipi è davvero diverso. Immagino sia quello che succede quando si telefona a tarda notte: -O – Pandincus

2

Hai provato

bigData2.Except(bigData1.AsQueryable()); 

Ho appena eseguito un esempio LINQ con 40 proprietà e 20.000.000 di righe e non mi imbatto in un problema.

(Prova questo esempio, purtroppo, non pieghevole in 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 ;} 
} 
+0

Immagino che il problema è che AnonymousType # 1 non può essere lanciato a AnonymousType # 2 ... la domanda è: perché sono due tipi diversi per cominciare? –

1

I tipi anonimi, come qualsiasi tipo, sono con il rispettivo assembly. Il compilatore può essere considerato uguale se i due adattatori sono nella stessa dll (in realtà, il modulo IIRC).

Al di là di questo, vorrei controllare i tipi di ...

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); 
     } 
    } 
} 
Problemi correlati