如何声明c#匿名类型而不创建它的实例?
本文关键字:创建 实例 类型 何声明 声明 | 更新日期: 2023-09-27 18:18:16
有没有更好的方法可以声明匿名类型,而不需要创建它的实例?
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表达式-然后忘记它们曾经存在过。
然而,你应该问自己为什么你需要这个。当你需要你的列表通过你的类给它的实体一个名字。在不同的作用域中使用相同的匿名类型有什么好处?要清晰准确。因此,每个开发人员都了解您的列表包含的内容以及他/她可以从中接受的内容。
因此,您最好使用(私有)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明确指出:
如果必须存储查询结果或将其传递到方法边界之外,请考虑使用普通的命名结构或类而不是匿名类型
然而,我不会像第二段中描述的那样将其限制在方法边界。
编辑:要回答你的问题,是否有可能在不实例化的情况下创建匿名类型,请参阅来自MSDN的这句话:
通过使用new操作符和an来创建匿名类型对象初始化器
EDIT2:从c# 7开始,你可以在列表中使用元组。然而,一个元组至少有两个属性,所以你的第一个例子在这里行不通:
var myList = new List<(string FirstName, string LastName)>();
myList.Add(("Boaty", "McBoatface"));
现在您可以检查您的其他列表是否包含这样的元组:
var contained = anotherList.Contains(("Boaty", "McBoatface"));
您可以创建匿名类型的变量而无需创建该类型的实例。
public static T DefaultReturnValue<T>(this Action<T> _) => default;
var initialVariable = DefaultReturnValue(() => new { Name = "x" });
来自lambda的操作永远不会执行。DefaultReturnValue
只提取返回类型
你可以稍后给这个变量赋值。
initialVariable = new { Name = "y" };
对于OP中的第二个示例使用此方法,可以声明初始HashSet变量,而无需创建HashSet的多余实例:
var hashSet = DefaultReturnValue(() => new [] { new { Name = (string)null } }.ToHashSet());