如何声明 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 }));
}
}
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"));
有没有更好的方法可以声明匿名类型,而无需求助于创建它的实例?
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 }));
}
}
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"));