Search code examples
c#anonymous-types

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


Is there a better way that can I declare an anonymous type, without resorting to create an instance of it?

var hashSet = new [] { new { Name = (string)null } }.Take(0).ToHashSet(); // HashSet<T>
using (new Scope())
{
    hashSet.Add(new { Name = "Boaty" });
    hashSet.Add(new { Name = "McBoatface" });
}
using (new AnotherScope())
{
    return names.Where(x => hashSet.Contains(new { x.Name }));
}

I dislike the hacky-looking approach taken in the first line above, but it does allow me to use the HashSet from within different scopes later.

EDIT: A second, slightly more comprehensive, example:

private IEnumerable<Person> _people;

public IEnumerable<Person> People()
{
    HashSet<T> hashSet;
    using (var new Scope())
    {
        // load a filter from somewhere else (oversimplified here to a single literal objects of an anonymous type)
        hashSet = new []
        {
            new { FirstName = "Boaty", LastName = "McBoatface" },
        }.ToHashSet();
    }
    using (var new AnotherScope())
    {
         return _people.Where(x => hashSet.Contains(new { FirstName = x.Nombre, LastName = x.Apellido }));
    }
}

Solution

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