对象初始化器
本文关键字:初始化 对象 | 更新日期: 2023-09-27 17:50:32
这两个代码片段都可以工作,但是,我想知道哪一个更好(如果有的话)。真的有区别吗?我所指的代码部分在LINQ中。如有任何见地,不胜感激。
select new Product {...
第一个片段:
public static IEnumerable<Product> GetProducts(IEnumerable<Product> products)
{
var query = from p in products
select new Product
{
Category = p.Category,
Id = p.Id,
CategoryId = p.CategoryId,
Name = p.Name
};
return query;
}
class Product
{
public int Id { get; set; }
public String Name { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; }
}
class Category
{
public int Id { get; set; }
public String CategoryName { get; set; }
}
第二个片段:
public static IEnumerable<Product> GetProducts(IEnumerable<Product> products)
{
var query = from p in products
select p;
return query;
}
class Product
{
public int Id { get; set; }
public String Name { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; }
}
class Category
{
public int Id { get; set; }
public String CategoryName { get; set; }
}
第一个代码片段将返回一个查询,当枚举时,该查询将创建products
可枚举对象中每个对象的副本,并遍历这些副本。(注意:如果输入对象的类型来源于Product
而不是Product
本身,那么您将把这些对象"切片"到Product
的实例中。)
第二个代码片段将返回一个查询,该查询在枚举时将按原始顺序遍历对象,并且在语义上与return products;
没有什么不同(假设products
不为空,也就是说——如果products
为空,则枚举时这两种变体都会抛出异常,但会抛出不同的异常类型)。
"tl;dr"版本是:第一种方法复制序列中的对象,第二种方法不复制。
当您需要对序列进行深度复制时,使用第一个,以便修改结果序列中的对象不会修改原始序列中的对象。如果您确实希望修改影响原始序列,则使用第二种方法,或您将不会修改两个序列中的任何一个。
旁白:如果您确实需要获取副本,请考虑在Product
类(public virtual Product Clone()
)上创建一个虚拟方法,以便(a)封装克隆逻辑,(b)如果派生Product
,则可以覆盖Clone()
以返回正确类型的副本。