A Generic List of Anonymous Class

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 :)

why can't I create a list T of anonymous type in C#?

You are missing some syntax. Anonymous types must be declared with new{...}. The property names must be declared when they cannot be inferred by a variable name. (You also have a typo in Add; it should be uppercase).

The below works:

var str = "string";
var num = 5;
var time = DateTime.UtcNow;
// notice double "new"
// property names inferred to match variable names
var list = new[] { new { str, num, time } }.ToList();

// "new" again. Must specify property names since they cannot be inferred
list.Add(new { str = "hi", num = 5, time = DateTime.Now });

Console.WriteLine(list[0].num);

With that said, this is pretty clunky. I'd suggest writing a class with the properties you want, or using ValueTuple.

This works and is clearer/cleaner:

var list = new List<(string str, int num, DateTime time)>();

// ValueTuple are declared in parens, method calls require parens as well
// so we end up with two sets of parens, both required
list.Add((str, num, time));
list.Add(("hi", 5, DateTime.Now));

Console.WriteLine(list[0].num);

Another reason to prefer your own class or ValueTuple is that you cannot declare a method as accepting an anonymous type. In otherwords, something like this is not valid:

public void DoSomethingWithAnonTypeList(List<???> theList ) { ... } 

There is nothing* I can put to replace the ??? as anonymous types are both internal and have "unspeakable" names. You wouldn't be able to pass your list around and do something meaningful with it. So what's the point?

Conversely, I can declare a method as accepting a list of ValueTuples:

public void DoSomethingWithTupleList(List<(string, int, DateTime)> theList) { 
Console.WriteLine(theList[0].Item1);
}

or using named tuples:

public void DoSomethingWithTupleList(List<(string str, int num, DateTime time)> theList) { 
Console.WriteLine(theList[0].time);
}

* You can technically pass your list of anonymous types to a generic method. However you won't be able to access the individual properties. The best you'd be able to do is access the list's Count or iterate over the list/enumerable and perhaps print the default ToString which doesn't really get you much either. There's not a generic constraint to help here. The third statement in this method will generate a compiler error:

public void DoSomethingGenerically<T>(List<T> theList) {

Console.WriteLine(theList.Count); // valid
Console.WriteLine(theList[0]); // valid, prints default ToString

Console.WriteLine(theList[0].num); // invalid! What's the point?

}

var list = new[] { new { str = "hi", num = 5, time = DateTime.Now } }.ToList();
// valid due to type inference, but see comments above
DoSomethingGenerically(list);

Do note that you'll have the same issue with ValueTuple, I'm just clarifying my "do nothing" statement.

Declaring list with anonymous type

It does not work because you have a typed list of MyDbTableEntity. You cannot add a different type on this typed list. Try to define the right type?

var finalEntries = new List<MyDbTableEntity>();

var groupedItemList = _context.MyDbTableEntity
.Select(k => new MyDbTableEntity { Name = k.name.ToString(), Data = k.info.ToString() })
.GroupBy(k => k.Name)
.ToList();

finalEntries.AddRange(groupedItemList);

or it or change it to a list of object.

var finalEntries = new List<object>();

// not sure about your type
var groupedItemList = _context.MyDbTableEntity
.Select(k => new { name = k.name.ToString(), data = k.info.ToString() })
.GroupBy(k => k.name)
.ToList();

finalEntries.AddRange(groupedItemList);

Importante: The problem of this is when you lose this scope you will not get a typed anonymous type, I mean, you will need to use some artifacts to read the properties, for sample: use reflection to convert the type into a dictionary.

Is there a trick in creating a generic list of anonymous type?

You can create an empty list for anonymous types and then use it, enjoying full intellisense and compile-time checks:

var list = Enumerable.Empty<object>()
.Select(r => new {A = 0, B = 0}) // prototype of anonymous type
.ToList();

list.Add(new { A = 4, B = 5 }); // adding actual values

Console.Write(list[0].A);

cast list of anonymous type to list of object

Here are the ways possible:

  1. Return a List<object>, which means you have no intellisense on the receiving end
  2. Return a List<dynamic>, which means you have no intellisense on the receiving end, but perhaps easier to access members you know are there than through reflection
  3. Return a List<T> but then you will have to provide an example of how T is supposed to look and this won't be any more safe at runtime than dynamic is
  4. Return a tuple of the new type that came with C# 7

Point 1 and 2 can be easily solved by just ensuring the list is of that type:

...
}.ToList<object>();

Point 3 is a hack but I'll post it below.

Point 4 can be solved with this syntax:

public List<(int Number, string Name)> GetData()
{

var list = new[]
{
(Number: 10, Name: "Smith"),
(Number: 10, Name: "John")
}.ToList();

return list;
}

This will give you intellisense for a while but the naming of the properties is a hack by the compiler and if you start passing these values around they will easily fall back to .Item1 and .Item2.


To cast an object to a specific type you can use a hack which only works in the same assembly that the anonymous object was created in, and that is that multiple anonymous types used around in your code, which has the same properties, in the same order, with the same property types, all end up being the same anonymous type.

You can thus cast an object to a specific anonymous type with this hackish code:

public T AnonymousCast<T>(object value, T example) => (T)value;
public IEnumerable<T> AnonymousCastAll<T>(IEnumerable<object> collection, T example) => collection.OfType<T>();

You would use it in your case like this:

var d = AnonymousCast(GetData()[0], new { Number = 0, Name = "" });

This is no more safe than using dynamic as there is no guarantee the object returned from GetData actually is of that anonymous type.

In short, use a named type.

Cannot convert system.generic.list anonymous type

This is an anonymous type:

select new 
{
COLDATE = DbFunctions.TruncateTime(b.COLDATE),
acode = b.acode,
LOCCODE = b.LOCCODE,
RESULT = b.RESULT,
analyte = b.analyte
}

The runtime has no idea how to convert it to your class

Why not changing it to

select new SCADA_DATA_Truncated
{
COLDATE = DbFunctions.TruncateTime(b.COLDATE),
acode = b.acode,
LOCCODE = b.LOCCODE,
RESULT = b.RESULT,
analyte = b.analyte
}

You can then remove the explicit cast altogether

Declaration of Anonymous types List

It involves a bit of hackery but it can be done.

static List<T> CreateListFromSingle<T>(T value) {
var list = new List<T>();
list.Add(value);
return list;
}

var list = CreateListFromSingle(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);

Anonymous class of generic type with method overloading

This solution is probably no more ideal than what's been discussed in the comments. However, if composition is an acceptable solution in your system, you might consider something like this before resorting to instrumentation:

public class WrapperClient<T extends BaseClient> extends BaseClient {
T realClient;

public WrapperClient(T realClient) {
this.realClient = realClient;
}

public void theMethod() {
realClient.theMethod();
someAdditionalLogic();
}
}

Then for the factory, have an abstract layer:

public abstract class WrapperClientFactory<T extends BaseClient> {
public final WrapperClient<T> create() {
T realClient = createRealClient();
return new WrapperClient<T>(realClient);
}

protected abstract T createRealClient();
}

Then the factory implementation could look like this

public class FooClientFactory extends WrapperClientFactory<FooClient> {
protected FooClient createRealClient() {
return new FooClient();
}
}

and then consumers would just do this:

BaseClient client = FooClientFactory.create();
client.theMethod();

Here, client would actually be an instance of WrapperClient, which would in turn delegate to FooClient, and not FooClient itself, so it's kind of hacky. But it would allow you to extend logic in arbitrary subclasses at the abstract layer.

If it's not important that consumers have a direct reference to the subclass they are actually using, I would prefer this approach to some of what has been discussed in the comments.

If this approach is mostly okay but the client subclasses need to be able to provide a different interface than the pure BaseClient, you could add another layer and make WrapperClient abstract.

Another downside to this approach is you lose the static methods in the factories. If this is important in your system, you could create a factory of factories that would hide instantiation from the consumer.

Constructing generic lists of anonymous types and nested loops

The simple answer is “you shouldn’t”.

There is a hacky trick which allows you to do it:

var myList = new[] { new { X = (object) null, Y = (object) null } }.ToList();
myList.Clear();
foreach (object x in GetAllX())
// ...

But it would really be more reasonable to use it the way it was intended:

var myList = GetAllX().Where(x => Process(x))
.SelectMany(x => GetAllY(x).Select(y => new { X = x, Y = y }))
.ToList();

If you really can’t use this pure-functional style for some reason, or you find you have to instantiate such a list in multiple places, you should probably declare a normal class instead of using an anonymous type. Remember that anonymous types are compiled into classes anyway, so there is no performance benefit to anonymous types, and even the readability/maintainability benefit is questionable if you have to resort to tricks like the hacky one at the top of this post.

Some people suggest to use List<dynamic>, but I recommend against it. It severely hampers maintainability because the property names and types are no longer checked at compile-time (you could mistype one and get a run-time bug); it slows down run-time performance because every access goes through the dynamic dispatcher; and also, once you put your objects into this list, you are basically stuck with them being dynamic, because you can’t cast them back to the anonymous type.

anonymous class as generic parameter

In the second piece of code,

    new Test<>(new Object(){
public String text = "Something";
}, (o) -> {
System.out.println(o.text);
});

compiles because the type argument of Test for the constructor call is inferred (since the diamond operator is used), and it is inferred to the anonymous type that the first argument evaluates to (the anonymous class type), and thus the second argument's type is operation<that anonymous class type>, which works.

In the first piece of code, the expression

    t.runOperation((o) -> {
System.out.println(o.text); // text cannot be resolved
})

does not compile. Here, the type of the lambda is inferred based on the type of the variable t, which is Test<?>. Thus, the argument of runOperation must be operation<some unknown type>. The only argument to runOperation that will work here is null.



Related Topics



Leave a reply



Submit