如何声明 C# 匿名类型而不创建它的实例?

How do I declare a C# anonymous type without creating 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 }));
}

我不喜欢上面第一行中采用的看起来很老套的方法,但它确实允许我稍后在不同范围内使用 HashSet。

编辑: 第二个,稍微更全面一点,例如:

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

事实上没有办法做到这一点,匿名对象总是有一些对象初始化(通过使用new)。

匿名类型是某种一劳永逸的类型,这意味着它们只使用一次——通常在一小段代码中,例如一个 LINQ 表达式,然后忘记它们曾经存在过。

但是您应该问问自己为什么需要这个。当您在 class 中需要您的列表时,请为其实体命名。在不同范围内使用相同的匿名类型有什么好处?要清楚和准确。因此每个开发人员都了解您的列表包含什么以及 he/she 可以从中接受什么。

所以你最好不要为此使用(私有的)struct,它也可以在你的方法中使用。

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

但是,我不会将其限制为第二段中所述的方法边界。

编辑:要回答您的问题是否可以在不实例化的情况下创建匿名类型,请参阅 MSDN 中的这句话:

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

EDIT2:从 C#7 开始,您可以在列表中使用元组。但是一个元组至少有两个属性,所以你的第一个例子在这里不起作用:

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

现在你可以检查你的其他列表是否包含这样一个元组:

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