Declaration of Anonymous Types List

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

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.

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"}}
);

why can't I create a listT 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.

Declaration of list of anonymous types

You could do it this way:

var reservations = new []
{
new { CustAcctNo = "", ReservNo = "", ReservStatus = "" }
}.ToList();

using (MainContextDB db = new MainContextDB())
{
reservations = (
from c in db.Reservations
select new
{
c.CustAcctNo, c.ReservNo, c.ReservStatus
}).ToList();
}

You just have to make sure you match the types on the members of your anonymous class.


The other option is to add a reference to the Microsoft Reactive Framework Team's "Interactive Extensions". They have a nice Using method for enmerables that lets you do this:

var reservations = 
EnumerableEx
.Using(
() => new MainContextDB(),
db =>
from c in db.Reservations
select new
{
c.CustAcctNo, c.ReservNo, c.ReservStatus
})
.ToList();

Declaring a LIST variable of an anonymous type in C#

Anonymous types, by their very nature, can't be explicitly "declared". They're anonymous, unknown; you don't have a type to declare. As such, anonymous types, whether directly or as a generic type parameter, cannot be specified as parameters, used as a return type, or stored to any explicitly typed variable. You must use var to assign them, and that means you're pretty much limited to using the type in local scope.

Your only option, basically, is to convert your anonymous type into a collected type that can be explicitly declared (i.e. you must declare the type itself). Just create a simple DTO class, and before calling ToList, run the anonymous type through a Select() Linq node that uses the anonymous type to initialize your strong class.

If you are using .NET 4.0, you COULD go dynamic. The dynamic keyword, and any object that's been passed through a parameter or return type declared dynamic, basically tells the compiler not to try to verify any operation performed on it; you can try to use any operator, call any method, etc. HOWEVER, if the operator, member, or whatever other operation you are performing isn't valid for what the object actually is behind the scenes, you'll get runtime exceptions which you must handle very robustly. For this reason, the dynamic feature of .NET 4.0 is not to be used lightly.

The only other thing you can do, as Kratz said, is return an ArrayList, or an Object[] array, and use reflection to discover the anonymous type's structure. It's a no-no pretty much any way you slice it; you lose the strong typing of the collection, your code bloats considerably as you need several lines of code to perform even the simplest get or set operations, and reflection, again by its nature, can be up to 100x slower than the equivalent operation on a known static type.

How do I declare a C# anonymous type without creating an instance of it?

In fact there is no way of doing this, an anonymous object always has some object-initialization (which is by using new).

Anonymous types are some kind of set and forget, which means use them once - usually within a short piece of code e.g. a LINQ-expression- and then forget that they ever existed.

However you should ask yourself why you need this at all. When you need your list throughin your class give its entites a name. What do you gain by using the same anonymous type in different scopes? Be clear and precise. Thus every developer understands what your list contains and what he/she can accept from it.

So you´d better be off using a (private) struct for this which can also be used within your method.

class CyClass
{
private struct Person { public string Name; }

HashSet<Person> hashSet = new HashSet<Person>();

...

using (var firstScope = new Scope())
{
hashSet.Add(new Person { Name = "Boaty" });
hashSet.Add(new Person { Name = "McBoatface" });
}

using (var secondScope = new AnotherScope())
{
return names.Where(x => hashSet.Contains(new Person{ x.Name }));
}
}

MSDN clearily states this:

If you must store query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type

However I won´t limit this to method-boundaries as described within my second paragraph.

EDIT: To answer your question if it´s possible to create an anonymous type without instantiating it, see this sentence also from MSDN:

You create anonymous types by using the new operator together with an
object initializer

EDIT2: As of C#7 you can use a tuple in your list. However a tuple has at least two properties, so your first example won´t work here:

var myList = new List<(string FirstName, string LastName)>();
myList.Add(("Boaty", "McBoatface"));

Now you can check if your other list contains such a tuple:

var contained = anotherList.Contains(("Boaty", "McBoatface"));

Creating a list of Anonymous Type in VB

Here's a handy method for creating a list of an anonymous type from a single anonymous type.

Public Function CreateListFromSingle(Of T)(ByVal p1 As T) As List(Of T)
Dim list As New List(Of T)
list.Add(p1)
return List
End Function

Now you can just do the following

Dim list = CreateListFromSingle(dsResource)

EDIT OP wanted a way to create the list before creating an element.

There are 2 ways to do this. You can use the following code to create an empty list. It borders on hacky because you are passing parameters you don't ever intend to use but it works.

  Public Function CreateEmptyList(Of T)(ByVal unused As T) As List(Of T)
Return New List(Of T)()
End Function

Dim x = CreateEmptyList(New With { .Name = String.Empty, .ID = 42 })


Related Topics



Leave a reply



Submit