6

I don't understand the difference between Anonymous Class and object Class

if i have an anonymous type object :

var x = new []
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name="s",phone=584}
        };

i can see how i can iterate through it and get values of the properties doing this x.name ...

but if i change this to an object

var x = new Object[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name="s",phone=584}
        };

then if i loop through it i will not be able to access the properties?? i have tried different ways to be able to get the values from this object and i failed, may be i missed something? and what is the point of generating object array and how can i consume it??

and i know that i can't do something like this : new Object[] {name = 'x' ...

Mina Gabriel
  • 23,150
  • 26
  • 96
  • 124
  • 1
    I've always thought that it was just an alias, like string/String, or object/Object – Deblaton Jean-Philippe May 06 '14 at 15:06
  • @mason just create a new string, and then press F12, you will see strings and objects are not primitive types – Deblaton Jean-Philippe May 06 '14 at 15:13
  • 2
    @mason C# doesn't really have a concept of "primitive type". It's a slang term, and one that's not well defined at that. You should avoid using it. Additionally, patxy is exactly right that `string` is just an alias to `String`. They are *entirely* interchangeable, and the compiler will simply replace all instances of `string` with `global::System.String` early on in its processing. There is no compelling reason to use one over the other in any given situation. (Unless you've done something evil like create your own `String` class, in which `string` will still refer to the system type.) – Servy May 06 '14 at 15:15
  • @Servy I never said you had to use one way or the other. I just said [what the common practice is](http://stackoverflow.com/questions/7074/whats-the-difference-between-string-and-string). That should be a compelling reason in itself. – mason May 06 '14 at 15:28
  • @Servy, strictly speaking, there are primitive types, as evidenced by the [Type.IsPrimitive](http://msdn.microsoft.com/en-us/library/system.type.isprimitive.aspx) property. These are types that are directly integrated into the CLR. Note that `String` is actually not a primitive type, though it does have some special status still (due to direct IL support for creating a new string instance from a constant value.) – Dan Bryant May 06 '14 at 15:36
  • @DanBryant I was careful with my termanology. **C#** has no concept of primitive types. The CLR does, as is referenced by that property, and other languages have the concept of primitive types, but in C# that's not a concept that exists, and it also has nothing to do with the types that have their own alias', as mason was stating. – Servy May 06 '14 at 15:39
  • 2
    @mason That's not a particularly widespread practice, nor is there any particularly compelling reason for that practice to exist. I pretty much never ever use `String`, and use `string` everywhere, personally, and even the post you yourself linked to stated that that is becoming the more common practice as suggested by MS. – Servy May 06 '14 at 15:41

3 Answers3

4

The object array can store any value. For example, this does not generate any error:

var x = new Object[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name = "s", phone = 584}
        };
x[0] = "foo";

Whereas the array of the anonymous class is strongly typed to that specific anonymous class. So, this would generate an error:

var x = new[]
        {
            new {name = "x", phone = 125},
            new {name = "f", phone = 859},
            new {name = "s", phone = 584}
        };
x[0] = "foo"; // Cannot implicitly convert type 'string' to 'AnonymousType#1'

In other words, the compiler ensures that the elements of the array of the anonymous class are only instances of that anonymous class (or null).

This is why when you write a loop like this:

for (var instance in x)
    Console.WriteLine(x.name);

It will work when x is declared as an array of the anonymous class, because the compiler can infer that all the elements of that array are instances of the anonymous class. However, when x is declared as an array of objects, the compiler cannot infer the actual types of the elements of that array (only that they inherit from Object, which includes all values in .NET).

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • is there is any way to iterate through the object and get values of the properties , one of the answers suggest `dynamic` and i know this is not a good practice – Mina Gabriel May 06 '14 at 15:26
  • @MinaGabriel It's not clear what you're trying to accomplish, so I can't say what the *best* answer is, but you could definitely use `dynamic` if you need to. You could also use reflection if you need more explicit control over how it iterates over the properties. From just the code that you've showed us, however, it's not at all clear that any of this is needed. Is there a reason why you want to go with an object array over the anonymous class array? – p.s.w.g May 06 '14 at 15:28
  • no i just wanted to know the difference between them – Mina Gabriel May 06 '14 at 15:30
1

In both cases arrays are strongly typed. In both cases, arrays contain objects of the same anonymous type. The only difference that in the first case the array has the type of the anonymous object, so the compiler knows of properties of the objects inside it, while in the second case the compiler does not know of these properties.

I have tried different ways to be able to get the values from this object and i failed, may be i missed something?

The properties, however remain there, and you can access them through reflection or by using dynamic type of C# 4:

var x = new Object[]
    {
        new {name = "x", phone = 125},
        new {name = "f", phone = 859},
        new {name="s",phone=584}
    };
var bigPhone = x.Cast<dynamic>().Where(v => v.phone > 500);
foreach (dynamic item in bigPhone) {
    Console.WriteLine("name={0}, phone={1}", item.name, item.phone);
}

Note that this solution is not an equivalent alternative to using a statically typed array from your first example. It is merely a work-around to a situation when the static type is lost.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The proper solution here is to infer the anonymous type's type, as is done in the OP's first example, not to use `dynamic`, which causes all sorts of problems. – Servy May 06 '14 at 15:17
  • @Servy There is no "proper" or "improper" solution here - in fact, OP's not asking what's proper and what's not, he's asking what's the difference. I am not suggesting him use the `dynamic` "solution", only show a way around un-typing the objects. – Sergey Kalinichenko May 06 '14 at 15:18
0

When you declare the variable as

var x = new Object[]
    {
        new {name = "x", phone = 125},
        new {name = "f", phone = 859},
        new {name="s", phone=584}
    };

x[whatever] is of type Object, so you can only use it as one. Object does not have fields as name and phone, so you naturally can't access them.

Gabriel Negut
  • 13,860
  • 4
  • 38
  • 45