Working with C# Anonymous Types

Working with C# Anonymous Types

You can't return a list of an anonymous type, it will have to be a list of object. Thus you will lose the type information.

Option 1
Don't use an anonymous type. If you are trying to use an anonymous type in more than one method, then create a real class.

Option 2
Don't downcast your anonymous type to object. (must be in one method)

var list = allContacts
.Select(c => new { c.ContactID, c.FullName })
.ToList();

foreach (var o in list) {
Console.WriteLine(o.ContactID);
}

Option 3
Use the dynamic keyword. (.NET 4 required)

foreach (dynamic o in list) {
Console.WriteLine(o.ContactID);
}

Option 4
Use some dirty reflection.

How should anonymous types be used in C#?

Anonymous types have nothing to do with the design of systems or even at the class level. They're a tool for developers to use when coding.

I don't even treat anonymous types as types per-se. I use them mainly as method-level anonymous tuples. If I query the database and then manipulate the results, I would rather create an anonymous type and use that rather than declare a whole new type that will never be used or known outside of the scope of my method.

For instance:

var query = from item in database.Items
// ...
select new { Id = item.Id, Name = item.Name };

return query.ToDictionary(item => item.Id, item => item.Name);

Nobody cares about `a, the anonymous type. It's there so you don't have to declare another class.

What are some examples of how anonymous types are useful?

I like to use anonymous types when I need to bind to a collection which doesn't exactly fit what I need. For example here's a sample from my app:

    var payments = from terms in contract.PaymentSchedule
select new
{
Description = terms.Description,
Term = terms.Term,
Total = terms.CalculatePaymentAmount(_total),
Type=terms.GetType().Name
};

Here I then bind a datagrid to payments.ToList(). the thing here is I can aggregate multiple objects without havign to define an intermidary.

Anonymous Type Member Equality

I believe the following code should generate two instances of the same anonymous type

No, it generates two instances of List<T>, with the same content.

So when you execute this:

if (letterFreq1.Equals(letterFreq2))

you're invoking the .Equals method on List<T> objects, which does not override the method inherited from System.Object, and thus do reference comparison.

You're right, however, in that the anonymous types would compare equal, and the two lists does in fact have the same content, but the list objects doesn't do content comparison by themselves, so they will compare as different.

If you were to coax the compiler into converting the two into the same type of collection, such as:

var letterFreq1 = CountLetters("aabbbc") as IEnumerable<object>;
var letterFreq2 = CountLetters("aabbbc") as IEnumerable<object>;

then you could compare their contents:

if (letterFreq1.SequenceEqual(letterFreq2))

but then you need to first know that they are collections, so depending on how general/generic your code is supposed to be, this may or may not be a solution for you.


My real advice, however, would be to avoid using anonymous types in this case. They're nice when used with local variables, but as you notice, when they escape the confines of a method they become very cumbersome to work with.

A better replacement would be a tuple:

void Main(string[] args)
{
var letterFreq1 = CountLetters("aabbbc");
var letterFreq2 = CountLetters("aabbbc");

if (letterFreq1.SequenceEqual(letterFreq2))
Console.WriteLine("Is anagram");
else
Console.WriteLine("Is not an anagram");
}

public static List<(char Letter, int Count)> CountLetters(string input)
=> input.ToCharArray()
.GroupBy(x => x)
.Select(x => (Letter: x.Key, Count : x.Count()))
.OrderBy(x => x.Letter)
.ToList();

An even better solution would be to create a named type for this, but again, depending on your situation this may or may not be a good solution for you.

C# anonymous object with properties from dictionary

You can't, basically. Anonymous types are created by the compiler, so they exist in your assembly with all the property names baked into them. (The property types aren't a problem in this case - as an implementation detail, the compiler creates a generic type and then creates an instance of that using appropriate type arguments.)

You're asking for a type with properties which are determined at execution time - which just doesn't fit with how anonymous types work. You'd have to basically compile code using it at execution time - which would then be a pain as it would be in a different assembly, and anonymous types are internal...

Perhaps you should use ExpandoObject instead? Then anything using dynamic will be able to access the properties as normal.

How does Distinct() work on a List of anonymous type?

From MSDN

Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashcode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

A generic list of anonymous class

You could do:

var list = new[] { o, o1 }.ToList();

There are lots of ways of skinning this cat, but basically they'll all use type inference somewhere - which means you've got to be calling a generic method (possibly as an extension method). Another example might be:

public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}

var list = CreateList(o, o1);

You get the idea :)



Related Topics



Leave a reply



Submit