0

どちらのコードスニペットも機能しますが、どちらが優れているのか疑問に思っています(もしあれば)。本当の違いはありますか?私が参照しているコードの一部は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; }
} 

2番目のスニペット:

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

1 に答える 1

1

最初のスニペットは、列挙されると、列挙可能な各オブジェクトのコピーproductsを作成し、それらのコピーを反復処理するクエリを返します。Product(警告:入力オブジェクトが実際にはそれ自体ではなく派生したタイプである場合は、Productそれらのオブジェクトをのインスタンスに「スライス」しますProduct。)

2番目のスニペットは、列挙されると元のシーケンスのオブジェクトを反復処理するクエリを返します。実際には、実行と意味的に違いはありませんreturn products;productsnullでない場合、つまり、両方のバリエーションが列挙されると例外がスローされます。 nullの場合products、ただし別の例外タイプがスローされます)。

「tl;dr」バージョンは次のとおりです。最初のアプローチはシーケンス内のオブジェクトをコピーしますが、2番目のアプローチはコピーしません。

結果のシーケンスのオブジェクトを変更しても元のシーケンスのオブジェクトが変更されないように、シーケンスのディープコピーを作成する必要がある場合は、最初のものを使用します。実際に元のシーケンスに影響を与える変更が必要な場合は、2番目のアプローチを使用してください。そうしないと、2つのシーケンスのどちらも変更しません。


余談ですが、コピーを作成する必要がある場合は、Productクラス(public virtual Product Clone())に仮想メソッドを作成して、(a)クローン作成ロジックをカプセル化し、(b)派生Productした場合は、オーバーライドClone()して適切に型指定されたコピーを返すことを検討してください。

于 2013-01-02T23:33:28.247 に答える