2010-07-23 7 views
7

OK OK, ich weiß, das ist ein Hack, aber das war für ein winziges Datenmanipulationsprojekt, und ich wollte herumspielen. ;-)Compiler-Optimierungen von anonymen Typen

Ich hatte immer den Eindruck, dass der Compiler alle anonymen Typen untersuchen würde, die in einem C# -Programm verwendet werden, und wenn die Eigenschaften identisch wären, würde nur eine Klasse hinter den Kulissen entstehen.

Also lassen Sie uns sagen, ich will einen anonymen Typ aus einigen typisierten Datensätzen erstellen, die ich habe:

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

ich jetzt tun können Spaß Dinge wie smallData2.Except (smallData1); usw., und alles funktioniert.

Nun, was ist, wenn ich ein größeres Paar anonyme Typen haben:

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

Wenn ich jetzt tun bigData2.Except (bigData1); der Compiler beschwert sich:

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

Warum? Zu viele Eigenschaften, also entscheidet der Compiler, dass es sich nicht lohnt zu optimieren?

Danke!

Antwort

2

Yep. Es ist nicht die Anzahl der Eigenschaften. Wie sicher sind Sie, dass Ihre Adapter genau dieselben Datentypen zurückgeben?

+0

Yup, die Adapter geben etwas unterschiedliche Datentypen zurück, aber der Unterschied ist nur die Art des typisierten Datasets (sie stammen aus verschiedenen Datenbanken). Alle Eigenschaften sind Zeichenfolgen, weshalb ich dachte, ich würde nur einen anonymen Typ verwenden, und das würde mich die Daten als EINE Art von Typ statt zwei behandeln lassen. – Pandincus

+0

OMG WO DAS DOPPELTE KOMMEN VON. Ähm ... okay, du hattest vollkommen recht. Einer der Typen ist tatsächlich anders. Ich schätze, das passiert, wenn du spät nachts kommst: -O – Pandincus

2

Haben Sie

versucht
bigData2.Except(bigData1.AsQueryable()); 

Ich habe gerade ein LINQ Beispiel mit 40 Eigenschaften laufen und 20.000.000 Zeilen und ich nicht in ein Problem laufen.

(Versuchen Sie, diese leider nicht zusammenklappbar Beispiel 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

Ich stelle mir das Problem ist, dass AnonymousType # 1 nicht zu AnonymousType # 2 gegossen werden ... die Frage ist, warum sind sie zwei verschiedene Arten zu beginnen? –

1

Anonyme Typen, wie jeder Typ, sind , die zu ihrer enthaltenden Baugruppe gehören. Der Compiler kann nur dann als gleich behandeln, wenn sich die beiden Adapter in derselben DLL befinden (eigentlich Modul IIRC).

Darüber hinaus würde ich die Typen überprüfen ...

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