英文:
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<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
})
};
}
答案1
得分: 0
我不建议较短一定更优,但有时我仍然更喜欢较短而不是更冗长的方式。
通过一些准备工作,创建一个将 ItemType
映射到访问器委托的 Dictionary<>
,您可以删除 switch
表达式。
private static Dictionary<ItemType, Func<ItemModel,long>> ItemIdAccessMap = new() {
{ ItemType.Item1, (ItemModel item) => item.ItemId1 },
{ ItemType.Item2, (ItemModel item) => item.ItemId2 },
{ ItemType.Item3, (ItemModel item) => item.ItemId3 },
{ ItemType.Item4, (ItemModel item) => item.ItemId4 },
};
我更喜欢颠倒 Join
的顺序,因为你无论如何都会丢弃与 itemList
匹配的成员。
private static IEnumerable<IdModel> GetResult(IEnumerable<ItemModel> itemList, IEnumerable<IdModel> idList, ItemType itemType)
=> idList.Join(
itemList,
id => id.Id,
ItemIdAccessMap[itemType],
(id, item) => 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<>
to map ItemType
s to accessor delegates, you can remove your switch
expression.
private static Dictionary<ItemType, Func<ItemModel,long>> ItemIdAccessMap = new() {
{ ItemType.Item1, (ItemModel item) => item.ItemId1 },
{ ItemType.Item2, (ItemModel item) => item.ItemId2 },
{ ItemType.Item3, (ItemModel item) => item.ItemId3 },
{ ItemType.Item4, (ItemModel item) => item.ItemId4 },
};
I prefer reversing the order of the Join
since you are throwing away the itemList
members that match anyway.
private static IEnumerable<IdModel> GetResult(IEnumerable<ItemModel> itemList, IEnumerable<IdModel> idList, ItemType itemType)
=> idList.Join(
itemList,
id => id.Id,
ItemIdAccessMap[itemType],
(id, item) => 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论