Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler optimizations of anonymous types

OK OK, I know this is a hack, but this was for a tiny data-manipulation project and I wanted to play around. ;-)

I was always under the impression that the compiler would examine all anonymous types used in a C# program and if the properties were the same, it would only create one class behind the scenes.

So let's say I want to create an anonymous type out of some typed datasets that I have:

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

I can now do fun things like smallData2.Except(smallData1); etc., and it all works.

Now, what if I have a bigger pair of anonymous types:

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

Now when I do bigData2.Except(bigData1); the compiler complains:

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

Why? Too many properties, so the compiler decides it's not worth it to optimize?

Thanks!

like image 942
Pandincus Avatar asked Jul 23 '10 01:07

Pandincus


People also ask

How to handle anonymous type in C#?

An anonymous type will always be local to the method where it is defined. It cannot be returned from the method. However, an anonymous type can be passed to the method as object type parameter, but it is not recommended. If you need to pass it to another method, then use struct or class instead of an anonymous type.

When you define an anonymous type the compiler converts the type into?

Anonymous types are class type, directly derived from “System. Object” so they are reference types. If two or more Anonymous types have same properties in same order in a same assembly then compiler treats them as same type. All properties of anonymous types are read only.

What is the difference between an anonymous type and a regular data type?

From the perspective of the common language runtime, an anonymous type is no different from any other reference type, except that it cannot be cast to any type except for object.

What are anonymous data types?

Anonymous types are class types that derive directly from object , and that cannot be cast to any type except object . The compiler provides a name for each anonymous type, although your application cannot access it.


2 Answers

Yep. Its not the number of properties. How sure are you that your adapters are returning exactly the same data types?

like image 81
Swanny Avatar answered Sep 28 '22 23:09

Swanny


Have you tried

bigData2.Except(bigData1.AsQueryable());

I've just run a LINQ example with 40 properties and 20,000,000 rows and I don't run into an issue.

(Try this unfortunately not collapsible example 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 ;}
}
like image 24
Matt Mitchell Avatar answered Sep 28 '22 22:09

Matt Mitchell