C# 3.0: I do not like Anonymous types

This is the my fifth post in the series of posts I am making on the new features in C#3.0. See the previous posts on var, extension methodlambda expressions and object-collection initializers

Before getting into why I do not like (actually hate) anonymous types in C#. Let's see what is this anonymous types and whats so special with this anonymity.

Anonymous types

Anonymous type is syntactic sugar to reduce typing. Let's say I need to create a structure or class to contain some data regarding customers. This is how you do it in C# 1.0

class Customer


private string name;

public string Name { get { return name; }
set { name = value; }}

private string address;

public string Address { get { return address; }
set { address = value; } }



Customer cust = new Customer();

cust.Name = "Abhinaba Basu";

cust.Address = "Hyderabad, India";

Or using the new Object initialization syntax of C#3.0 as

var cust = new Customer{Name = "Abhinaba Basu",
Address =
"Hyderabad, India"};

This is a very repitative code pattern of creating data only containers (class or struct) for the related data types. This is can be done with the Anonymous method syntax as

var cust1 = new { Name = "Abhinaba Basu",
Address =
"Hyderabad, India" };

Note that in this statement I have not named a type and hence the compiler emits code to generate a new class definition whose name is not know to us and hence is a Anonymous type. The following code is generated. 

public sealed class <Projection>f__0


// Methods

public <Projection>f__0();

public override bool Equals(object);

public override int GetHashCode();

public override string ToString();

// Properties

public string Address { get; set; }

public string Name { get; set; }

// Fields

private string _Address;

private string _Name;


Here <Projection>f__0 is the generated class' name. For each member a private field and the corresponding property is generated. The class also generates proper implementation to override Equals, GetHashCode and ToString methods based on each of the fields. The rest of the code is same as that used for Object initialization.

If we have two such declaration that match in the field types then the same class will be used for both of them.

var cust1 = new { Name = "Abhinaba", Address = "Hyderabad" };

var cust2 = new { Name = "Ankur", Address = "Noida"};

if (cust1.GetType() == cust2.GetType())

Console.WriteLine("Cust1 and Cust2 are of the same type {0}",

// output:

// Cust1 and Cust2 are of the same type
// AnonymousTypes.Program+<Projection>f__0

There are couple of interesting point here

  • The whole thing works only for classes where you do not need to add methods
  • You have to accept the compilers implementaion of the overrides.
  • This works in situation where you are actually not interested to know the name of the generated class
  • All the fields in the class are implicitely typed (var). So the compiler figures out the type to use (Age is Int32)

You can also use nested declaration as in

var cust = new { Name = "Abhinaba Basu",
Address =
"Hyderabad, India",

Phone = new { AreaCode = 33, Number = 444444}};

Why I do not like anonymous types

Again due to my upbringing in C/C++ I did not like implicit types when I saw it. This is taking the same idea to an extreme. Now not only are we letting the compiler choose the type for me I am also letting it generate new types!!!

Even without my pre-disposition I think that this construct address some special programming cases and should not have been included in the language. It'll just add to the surface area and learning curve and mainly go unused. The unusability comes from the following reasons

  • Flexibility is lost. Today I have a data type that has only data and right now I do not care about the exact type. If in the future I need to add some method to it (say to change the Equals override) I need to change all the places where I used the anonymous types and convert them to named types.
  • I decide to add a new field to the class which is used by some of the object and not by some. At the same time I need all of the objects to be of the same type (maybe because I compare them) then I need to go and make changes at all the object allocation code
    var cust = new { Name = "Abhinaba Basu", Address = "Hyderabad, India", phone }
  • Readability of the code is lost. If I have an API like void Show(var value) and I call it as follows
    var cust = new { Name = "foo", Address="bar");
    then this does not convey much. The alternative is much more readable when void Show (Customer cust) is defined and used as follows
    Customer cust = new Customer { Name = "foo", Address="bar");
    Show (cust);

Comments (26)

  1. damien morton says:

    I kinda like this new notation, but only as a way of bringing together various query results. Clearly, these anonymous types arent usefull beyond the scope in which they are created, except as a data-holding class that can be reflected over.

    It would be usefull to be able to constrain these anonymous types to be immutable and/or structs.

    var cust = [Immutable.Class] new { Name="foo", Address="bar"}

    var cust = [Immutable.Struct] new { Name="foo", Address="bar"}

    or something like that.

  2. Joe Chung says:

    There is something deliciously ironic about a C/C++ programmer complaining about new language features causing code to become unreadable. Is it the voice of experience perhaps? 😉

  3. Gabe says:

    I think that perhaps your dislike of C#’s new features stems from the fact that you are looking at the new features and trying to imagine how you would use them within the context of your current programming patterns. However, these new features are designed to be used in completely new ways.

    Anonymous types are not meant to be used in places where you would care about their name or method overriding — in those cases you should use a class. Anonymous types are for when you want to just group together a bunch of data items. Perhaps you are running a query that returnsa few arbitrary pieces of data, or maybe you have a function that needs to return multiple pieces of data. Can you imagine what it would be like if you had to create a new class for each different query in an application?

    C# 3.0’s new set-based operators (LINQ) give us wonderful new tools for working with data sets. One thing we frequently need is objects which do nothing besides hold data to iterate over. Do you want to define a datatype for every query that returns a different set of columns? Quite frankly, it’s a pain in the butt. It leads to a proliferation of meaningless types, type unsafety (just using objects), or somewhere inbetween (having a bunch of standard types and only filling in whatever data is returned because maintaining the types every time a query changes becomes too much work).

    The type proliferation problem is especially bad in Java where each class requires its own file. As a side note, I once wrote a compiler for a language with lexical scoping (like Pascal, where a function could have an inner function that can access the local variables of its outer function). This means that each local variable scope requires its own separate data structure, which would have to have its own separate class file if the compiler were targeting the JVM. What’s the point of having a whole bunch of classes with no methods and every member public?

    internal class CustomerName_OrderCount { public string Name; public int Count; }

    internal class CustomerName_Country { public string Name; public string Country; }

    internal class CustomerName_Country_State_Phone { public string Name; public string Country; public string State; public string Phone; }

    internal class CustomerName_Country_State_Phone_OrderCount { public string Name; public string Country; public string State; public string Phone; public int Count; }

    I wouldn’t want an unnecessary mess like that cluttering up my code.

    Additionally, though, having anonymous types means that the compiler knows that calling the constructor and properties have no side-effects, which allows it to reason about the values in ways it otherwise could not. This is important for being able to translate queries to SQL and know that you’re getting the correct semantics.

  4. Casey says:



    Code readability wins every time. And making something slightly shorter does not enhance readability one iota.

    Have to agree on every point in your post. Mostly thats because I spend my days dealing with less than competent developers, and anything that makes it easier for them to be even worse is not a good idea.

  5. I absolutely agree that in some situation these features come in handy as in creating data types out of Linq queries. If you talk to a function programmer he’ll tell you in length that life without continuation support is not possible. The point is all of them have their context and usage. If you try to pull in all of them into the same language and point to individual usage as the justification soon you’ll have a language which’ll be too huge and complex to use. Every language has a nature and people using it are used to it. We all know that object oriented design works well in some situation so does that mean that functional languages will start using them? They won’t, and similarly C# should not start adopting functional programming paradigm, cause its so different for people moving into C# from C/C++ background that they’ll get alienated when they get to maintain code with Lambda expressions and anonymous types/methods. As Joe Chung has pointed out this is the voice of experience. Wait till Boost lib starts getting standardized into ANSI C++ and as a C++ dev you suddently get code like for_each(a.begin(), a.end(), std::cout &lt;&lt; _1 &lt;&lt; ‘ ‘); to maintain.

  6. Jeff Parker says:

    I agree I do not like it either Explicit leads to good code, Implicit leads to hours and hours of debugging and fixing problems and bad code getting out.

    Implicit makes it to easy to screw it up. I remember a guy one time came to me with a problem in his code. It was thousands of lines of vb 6 code. I turned on Option Explicit the went through and manually redeclaired everything. Found the problem easily since things were explicitly declaired the compiler showed me right where the error was. I gave the guy back his code working flawlessly and faster than every before. He went and complained to my boss because I went through and put all these "dim" statements in his code everywhere and somehow forced him to use them too.

    Now you have a million programmers out there like this fellow that didn’t know what a dim was but somehow managed to become a "Professional Programmer" C# really cleaned a lot of that up. It forced you to become a better programmer. Now that looks like it is all going out the window.

  7. Hasani says:

    "Wait till Boost lib starts getting standardized into ANSI C++"

    I’ve been holding my breath for 3 years now =(

  8. "Readability of the code is lost. If I have an API like void Show(var value) and I call it as follows

    var cust = new { Name = "foo", Address="bar");


    then this does not convey much. The alternative is much more readable when void Show (Customer cust) is defined and used as follows

    Customer cust = new Customer { Name = "foo", Address="bar");

    Show (cust);


    That example is not legal according to the current plans. Anonymous types can not exit the scope of the current method. That is you can only use var as the type of a local, it may not be a parameter, return type, or field.

    Hope that clarifies at least that portion of your concern.

    I think that one interesting thing about anonymous types is that they allow me to change the shape of my query results easily. I personally think that will be useful when first determining what query I want, even if I then introduced a named type.

  9. I did not see in the spec that anonymous types cannot exit the scope of the current method. If this is true then a lot of my concerns are gone as the type will be used locally in a function and hence chances of passing them around and creating ambiguity is gone.

    Anonymous types does work beautifully in case of grouping data in Linq queries. Which I plan to cover in my next post.

  10. damien morton says:

    I havent seen anything in explicitly in the spec about the scope thing either.

    It looks to me, however, that you cant return anonymous types from a method as anything but type object, and that, at least for now, these anonymous types dont implement any interfaces.

    You cant define a method as returning type ‘var’, nor does there seem to be a way of using inference to migrate anonymous type bindings into outer generic type declarations. You can pass them down into called generic methods, however.

  11. Gabe says:

    I think it’s safe to say that you can return anonymous types from a function — that’s how functions like .Select() work!

    In order to do "select x.Name, x.Age", the compiler creates a function that takes an x and returns a new {string Name, int Age}; it then passes that function to .Select(), which returns an IEnumerable<{string Name,int Age}>.

    So while you may not be able to specify ‘var’ as the return type of a method, you can absolutely return these types from functions!

  12. Thong Nguyen says:

    Again, I have to disagree.

    You won’t use anonymous types everywhere willy nilly but think of cases where you would return a small array or a pair<a,b>. Anonymous types suddenly are actually clearer that the alternative.

    All language features can be abused (goto in c#?) but they all have their uses. I wish people would stop trying to protect programmers from themselves (we aren’t all morts) by limiting the expressiveness of the language.

  13. Will Sossamon [MVP] says:

    I think your hate of anonymous types is erroneous. I have some across many people mistaking ‘var’ as an equivalent to the Variant type of VBScript or JavaScript. It is, like you described anonymous types, syntactic sugar, nothing more. You mention that readability is lost, such as the API ‘Show(var value)’ implying that somehow ‘value’ has no strong type and is a variant. This concept does not exist in the C# 3.0 spec. According to the C# 3.0 language specification, this piece of code would not compile since there is no initializer, and thus nothing to infer the type from.

    For more info, see section 26.1 of the C# 3.0 Language Spec: http://download.microsoft.com/download/9/5/0/9503e33e-fde6-4aed-b5d0-ffe749822f1b/csharp%203.0%20specification.doc

  14. hobbit says:

    it’s funny how many people don’t seem to understand "var" at all and have jumped to the conclusion that it’s similar or the same as VB6’s "Variant" data type.

    i hate how every time a nice new language feature comes out there’s a giant crowd of people complaining because they don’t want to learn something new or they’re afraid that they’ll shoot their eye out with it.

  15. "I agree I do not like it either Explicit leads to good code, Implicit leads to hours and hours of debugging and fixing problems and bad code getting out.

    Implicit makes it to easy to screw it up. I remember a guy one time came to me with a problem in his code. It was thousands of lines of vb 6 code. I turned on Option Explicit the went through and manually redeclaired everything."

    C# implicit typing will be resolved at compile time. If there are typesafety errors, the compiler will happily find them for you.

    Actually, if people use this for returned data results, it may replace situations where the returned data is being handled with DataTables and DataSets. The field values inside a DataTable are not very typesafe, because they require runtime downcasting to extract the values.

  16. Jerod Moemeka says:

    The problem with anonymous types isn’t that they can ‘break’ things. As mentioned earlier you cannot use them outside of the scope of methods.  The problem is there isn’t mush you CAN do with them.  So I used them as data containers for a query result then what, I have to iterate through my result using reflection of all things to get my data back!?!  just what in heavens name are you supposed to do with a complex nested result set when you don’t knwo what the type name is and there’s no way to explicitly access all the properties you’ve created?

  17. It’s been years since I last saw you.

    ,It’s been years since I last saw you.

    ,It’s been years since I last saw you.

    ,It’s been years since I last saw you.

  18. It’s been years since I last saw you.

    ,It’s been years since I last saw you.

    ,It’s been years since I last saw you.

    ,It’s been years since I last saw you.

  19. louis atamja says:

    please there a certain web which cannot browse through till the end without having complain from the company so please i will like you to give me or to discribe me a good proxy to use that will help me open these web please these web are many and especialy in cameroon they are website like kansas.com,kansascity.com


  20. Dave says:

    1)  Obviously, Microsoft needed anonymous types for LINQ.  Someone would complain if they didn’t expose that for the rest of us.

    2)  I can write unreadable code with or without anonymous types and I can write readable code WITH anonymous types.  The problem isn’t anonymous types, the problem is the person using it.

    3)  Just because a feature is available doesn’t mean it should be used all of the time.  Ternary operators are also useful occasionally, but programmer in their right mind would consider using them in place of a standard if/then/else construct.  (Of course, you could find programmers who are out of their minds who do use them in place of if/then/else.)

  21. Dave, you just established the case for supporting typedefs, macros, a bunch of additional operator overloading (new?), optional parameteres, swtich-case fall through.

    All of these were excluded from C# with the logic that that programmer will write more readable and less error prone code. Why do you think C# is more reabale than Lisp or Haskell?

  22. George says:

    I was initially suspicious but having read through this thoughtful discussion on both sides, I am comforted 🙂

    And in fact, many times the structure of data mirrors the structure of code. Having a flexible bag to hold arbitrary typed collections, and so avoid the ugliness of casting and obfuscation indexed references, is nice.

    After all, the holy grail is clarity.

    for example (contrieved)…

    var x

    if (a)

     x = new {y,c,b,…}


     x = new {y,c,a,…}


    for (int i = 0; i < x.y;…)

     if (x.c)


     else if (x.b)


     else if (x.a)


  23. Mark Sowul says:

    George, that won’t compile.  vars must be initialized at declaration time.

    Anyway since vars and anonymous types are still statically typed and are confined to the scope of a single method, I don’t see what the fuss is about.  Obviously their primary purpose is for LINQ. (The only way to get them out of a method is with generics, which is how LINQ does it.  And this is perfectly reasonable, as that’s the point of generics – to be generic).

  24. rx says:

    anonymous types are a benefit when you are creating view objects from a linq query.  You don’t know how to use it properly

  25. I have to disagree, but I understand where you are coming from. I am a long time C/C++ programmer and I am often the most experienced programmer in the group.

    As a previous poster mentioned you are missing the point of anonymous types if you are considering thier use outside of LINQ type usage.

    Anonymous types are method local, so they shouldnt be passed back as a return type of accepted as a method parameter (unless you are extending LINQ).

    Someone mentioned implicit versus explicit — the whole reason *I despise* VB. I like explicit code and strong types. However, in this case "explicit versus implicit" is the wrong perspective, it is rather about "declaritive versus imperative" programming and declaritive code is more desired.

    declaritive versus imperative from wiki:

    "In computer science, declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow. Many languages applying this style attempt to minimize or eliminate side effects by describing what the program should accomplish, rather than describing how to go about accomplishing it. This is in contrast with imperative programming, which requires an explicitly provided algorithm."

    Notice the "…in attempt to minimize or eliminate side effects…", that is what anonymous types and LINQ are giving us. It’s all for the purpose of less bugs/errors in our code.

    More code = more coverage for bugs/errors/undesired-behaviour to occur. After 15 years of programming applications I understand that each new module that expands my code base adds a lot of code I have to support, debug, etc. Writing new code is easy and quick, perfecting it for the pounding the general user will give it takes *a lot* of time! More behavioural constructs are the answer. In the future I would like to see the end user be able to program with behavioural programming. The user says, "Computer: I want a program to do *this* and *that*!" [beep blop bleep]…my new custom application is ready. (…and, by the way, all the internal types would be anonymous.)

Skip to main content