在LINQ中的”Delegate func”

huangapple go评论71阅读模式
英文:

Delegate func in LINQ

问题

我有一个关于优化我的代码的问题。
是否可以创建一个方法,根据ItemType返回必要的outerKeySelector(例如 i => i.ItemId1,i => i.ItemId2 等等)作为Join的func?

谢谢!

public class ItemModel
{
    public long ItemId1 { get; set; }
    public long ItemId2 { get; set; }
    public long ItemId3 { get; set; }
    public long ItemId4 { get; set; }
}

public class IdModel
{
    public long Id { get; set; }
    public decimal Quantity { get; set; }
}

public enum ItemType
{
    Item1,
    Item2,
    Item3,
    Item4
}

我相信它可以更短一些)

private static IEnumerable<IdModel> GetResult(IEnumerable<ItemModel> itemList, IEnumerable<IdModel> idList, ItemType itemType)
{
    return itemType switch
    {
        ItemType.Item1 => itemList.Join(idList,
            i => i.ItemId1,
            j => j.Id,
            (i, j) => new IdModel()
            {
                Id = j.Id,
                Quantity = j.Quantity
            }),
        ItemType.Item2 => itemList.Join(idList,
            i => i.ItemId2,
            j => j.Id,
            (i, j) => new IdModel()
            {
                Id = j.Id,
                Quantity = j.Quantity
            })
    };
}
英文:

I have a problem with optimizing my code).
Is it possible to create a method that returns necessary outerKeySelector (i => i.ItemId1, i => i.ItemId2 etc.) as func for Join that depends from ItemType ?

Thanks!

    public class ItemModel
    {
        public long ItemId1 { get; set; }
        public long ItemId2 { get; set; }
        public long ItemId3 { get; set; }
        public long ItemId4 { get; set; }
    }

    public class IdModel
    {
        public long Id { get; set; }
        public decimal Quantity { get; set; }
    }

    public enum ItemType
    {
        Item1,
        Item2,
        Item3,
        Item4
    }
 

I believe it could be much shorter)

private static IEnumerable&lt;IdModel&gt; GetResult(IEnumerable&lt;ItemModel&gt; itemList, IEnumerable&lt;IdModel&gt; idList, ItemType itemType)
        {
            return itemType switch
            {
                ItemType.Item1 =&gt; itemList.Join(idList,
                    i =&gt; i.ItemId1,
                    j =&gt; j.Id,
                    (i, j) =&gt; new IdModel()
                    {
                        Id = j.Id,
                        Quantity = j.Quantity
                    }),
                ItemType.Item2 =&gt; itemList.Join(idList,
                    i =&gt; i.ItemId2,
                    j =&gt; j.Id,
                    (i, j) =&gt; new IdModel()
                    {
                        Id = j.Id,
                        Quantity = j.Quantity
                    })
            };
        }

答案1

得分: 0

我不建议较短一定更优,但有时我仍然更喜欢较短而不是更冗长的方式。

通过一些准备工作,创建一个将 ItemType 映射到访问器委托的 Dictionary&lt;&gt;,您可以删除 switch 表达式。

private static Dictionary&lt;ItemType, Func&lt;ItemModel,long&gt;&gt; ItemIdAccessMap = new() {
    { ItemType.Item1, (ItemModel item) =&gt; item.ItemId1 },
    { ItemType.Item2, (ItemModel item) =&gt; item.ItemId2 },
    { ItemType.Item3, (ItemModel item) =&gt; item.ItemId3 },
    { ItemType.Item4, (ItemModel item) =&gt; item.ItemId4 },
};

我更喜欢颠倒 Join 的顺序,因为你无论如何都会丢弃与 itemList 匹配的成员。

private static IEnumerable&lt;IdModel&gt; GetResult(IEnumerable&lt;ItemModel&gt; itemList, IEnumerable&lt;IdModel&gt; idList, ItemType itemType)
    =&gt; idList.Join(
                itemList,
                id =&gt; id.Id,
                ItemIdAccessMap[itemType],
                (id, item) =&gt; id
       );

如果您担心需要处理所有 ItemType 成员,您可以使用反射来动态创建委托,但这会增加一些启动时的运行时开销。

英文:

I wouldn't suggest shorter is necessarily more optimal, but I sometimes prefer shorter to more verbose anyway.

With a little preparation work creating a Dictionary&lt;&gt; to map ItemTypes to accessor delegates, you can remove your switch expression.

private static Dictionary&lt;ItemType, Func&lt;ItemModel,long&gt;&gt; ItemIdAccessMap = new() {
    { ItemType.Item1, (ItemModel item) =&gt; item.ItemId1 },
    { ItemType.Item2, (ItemModel item) =&gt; item.ItemId2 },
    { ItemType.Item3, (ItemModel item) =&gt; item.ItemId3 },
    { ItemType.Item4, (ItemModel item) =&gt; item.ItemId4 },
};

I prefer reversing the order of the Join since you are throwing away the itemList members that match anyway.

private static IEnumerable&lt;IdModel&gt; GetResult(IEnumerable&lt;ItemModel&gt; itemList, IEnumerable&lt;IdModel&gt; idList, ItemType itemType)
    =&gt; idList.Join(
                itemList,
                id =&gt; id.Id,
                ItemIdAccessMap[itemType],
                (id, item) =&gt; id
       );

If you are concerned with having all ItemType members being handled, you could use Reflection to create the delegates dynamically, at the expense of some startup runtime.

huangapple
  • 本文由 发表于 2023年6月22日 03:34:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定