I have populated the follow list with objects of type AnonymousType
List<object> someList = new List<object>();
someList.Add(new { foo = 1 });
My problem is that I can't make it stronly typed to do something like this:
someList.Where(x=> x.foo == 1);
However, it's possible on this list:
var someList = new[] { new { foo = 1 } };
Can I cast my first list to make it behave like the second list? I want to be able to use lambda expressions on the properties like I showed above.
You create anonymous types by using the new operator together with an object initializer. For more information about object initializers, see Object and Collection Initializers. The following example shows an anonymous type that is initialized with two properties named Amount and Message .
You create an anonymous type using the new operator with an object initializer syntax. The implicitly typed variable- var is used to hold the reference of anonymous types.
An anonymous object is basically a value that has been created but has no name. Since they have no name, there's no other way to refer to them beyond the point where they are created. Consequently, they have “expression scope,” meaning they are created, evaluated, and destroyed everything within a single expression.
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.
You can take advantage of generics and type inference to create the list for you:
public static List<T> CreateAnonymousList<T>(params T[] entries)
{
return new List<T>(entries);
}
Usage like:
var someList = CreateAnonymousList(new { foo = 1 }, new { foo = 2 }, new { foo = 1 });
someList.Where(x => x.foo == 1);
Naturally you won't be able to do much with it. You'll never be able to strongly type it in your code to anything other than var
or return it out from your method or anything you normally wouldn't be able to do with anonymous types. If you want to do more, you'll just have to bite the (small) bullet and define a class for your anonymous type.
Rereading your question, you can still perform LINQ queries on an array:
var someArray = new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }};
someArray.Where(x => x.foo == 1)
So unless you are modifying it (say via standard List<T>
operations like Add
or Remove
) then there's no reason to have to convert it to a List<T>
.
I realize that maybe you want to still be able to pass it back (for some reason) and still do operations on it without knowing its anonymous type. In that case you could treat it as dynamic
and perform the operations at runtime, but you lose any intellisense/strong typing that you'd normally have with the anonymous type:
List<dynamic> someDynamicList = new List<dynamic>() {new { foo = 1 }, new { foo = 2 }, new { foo = 1 }};
someDynamicList.Where(x => x.foo == 1)
One last method as pointed out by Tim Schmelter leveraging Jon Skeet's CastByExample, but extended to convert your collection with an extension method:
public static IEnumerable<T> CastByExample<T>(this IEnumerable source, T example)
{
foreach(object entry in source)
yield return (T)entry;
}
public static IEnumerable CreateAnonymousData()
{
return new[]{new { foo = 1 }, new { foo = 2 }, new { foo = 1 }};
}
With usage like:
var anonymousData = CreateAnonymousData();
var typedAnonymousData = anonymousData.CastByExample(new { foo = 1 });
typedAnonymousData.Where(x => x.foo == 1);
This takes advantage of the fact that within the same assembly, anonymous types declared with the same parameter names, types, and order compile to the same type. This won't work if you need to call your CreateAnonymousData
from outside the current assembly and you have to maintain the signature of your foo
anonymous type everywhere you use it (add/change its signature, you must update it everywhere you use it or you're going to have a bad time).
But I think it's becoming more clear now that the best solution to this is to simply define a class representation of your anonymous type.
You can use Jon Skeets' CastByExample
:
public static T CastByExample<T>(object input, T example)
{
return (T)input;
}
List<object> someList = new List<object>() {
new { foo = 1 },new { foo = 2 },new { foo = 3 }
};
var example = new { foo = 0 };
foreach (object obj in someList)
{
var x = CastByExample(obj, example);
Console.WriteLine("Foo: " + x.foo);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With