如何通过使用委托/lambda 来避免重复的代码

发布于 2024-10-10 08:09:50 字数 1563 浏览 5 评论 0原文

我下面有这段代码,它循环遍历数据结构建立一个字典。

我将此代码重复多次,唯一的区别是字典的键,

因此在下面的代码中它恰好是:

  task.Project + task.Name

这是字典的键,但在其他情况下它只是:

 task.Project

或者只是

 task.Name

这里是其中之一的示例hte 硬编码的“Bucket”方法。

我的目标是拥有一个通用的“Bucket”方法,我可以在其中进行回调或以某种方式传递用于计算密钥的函数。

这样做的最好方法是什么?

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
    Dictionary<string, TeamHours> dict = new Dictionary<string, TeamHours>();

    foreach (var name in timebookings.Keys)
    {
        TimeBooking tb = timebookings[name];
        Person p = tb.Person;

        foreach (var booking in tb.WeeklyTimeBookings.Keys)
        {
            var item = tb.WeeklyTimeBookings[booking];
            foreach (var task in item.TaskSlices)
            {
                if (dict.ContainsKey(task.Project + task.Name))
                {
                    TeamHours th = dict[task.Project + task.Name];
                    th.Hours = th.Hours + task.Hours;
                }
                else
                {
                    TeamHours th = new TeamHours();
                    th.Hours = task.Hours;
                    th.Project = task.Project;
                    th.Task = task.Name;
                    th.Workstream = tb.Person.OrganisationalUnitName;
                    dict[task.Project + task.Name] = th;
                }
            }

        }

    }
    return dict;
}

i have this code below that loops through a data structure builds up a dictionary.

I have this code duplicated multiple times with the only difference being the Key to the dictionary

so in the below code it happens to be:

  task.Project + task.Name

that is the key to the dictionary but in other cases its just:

 task.Project

or just

 task.Name

here is an example of one of hte hard coded "Bucket" methods.

My goal is to have a generic "Bucket" method where i can have a callback or some way to pass in the function for calculating the key.

What is the best way of doing this ??

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
    Dictionary<string, TeamHours> dict = new Dictionary<string, TeamHours>();

    foreach (var name in timebookings.Keys)
    {
        TimeBooking tb = timebookings[name];
        Person p = tb.Person;

        foreach (var booking in tb.WeeklyTimeBookings.Keys)
        {
            var item = tb.WeeklyTimeBookings[booking];
            foreach (var task in item.TaskSlices)
            {
                if (dict.ContainsKey(task.Project + task.Name))
                {
                    TeamHours th = dict[task.Project + task.Name];
                    th.Hours = th.Hours + task.Hours;
                }
                else
                {
                    TeamHours th = new TeamHours();
                    th.Hours = task.Hours;
                    th.Project = task.Project;
                    th.Task = task.Name;
                    th.Workstream = tb.Person.OrganisationalUnitName;
                    dict[task.Project + task.Name] = th;
                }
            }

        }

    }
    return dict;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

最美的太阳 2024-10-17 08:09:50

嗯,你基本上自己回答了这个问题。要么将委托传递到方法中,要么继承不同的实现并通过实现抽象方法进行专门化。另一种选择是将密钥构建算法分离为接口,这可以实现最佳的关注点分离,但对于简单的场景来说,开销可能太大。

选项 1 — 委托

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings, Func<string, Task> getTaskKey)
{
    …
    dict[getTaskKey(task)] = th;
    …
}

适合在高度本地化的场景中使用(即单个类私有的实现和使用),只需一些简单的密钥构建表达式。

选项 2 — 抽象类和方法

class abstract BucketAlgorithm
{
    protected abstract string GetTaskKey(Task task);


    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[GetTaskKey(task)] = th;
        …
    }
}

class SpecificBucketAlgorithm : BucketAlgorithm
{
    protected override string GetTaskKey(Task task) { … }
}

适合在中等范围内使用,例如一个程序集,其中不需要更好地分离关注点(接口与实现),或者需要多个重要的密钥构建算法。

选项 3 — 分解为接口

interface ITaskKeyGenerator
{
    string GetTaskKey(Task task);
}

class BucketAlgorithm
{
    public BucketAlgorithm(ITaskKeyGenerator taskKeyGenerator)
    {
        this.taskKeyGenerator = taskKeyGenerator;
    }

    private ITaskKeyGenerator taskKeyGenerator;

    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[taskKeyGenerator.GetTaskKey(task)] = th;
        …
    }
}

适合需要彻底分离关注点或可能存在多个复杂密钥构建算法的场景,甚至是由 API 用户从“外部”提供的场景。

Well, you mostly answered the question yourself. Either pass a delegate into the method or inherit different implementations and specialize by implementing an abstract method. Another option is separating the key-building algorithm as an interface, which leads to best separation of concerns, but the overhead might be too much for simple scenarios.

Option 1 — delegates

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings, Func<string, Task> getTaskKey)
{
    …
    dict[getTaskKey(task)] = th;
    …
}

Good for use in highly-localized scenarios (i.e. implementation and usages private to a single class) with just a few simple key-building expressions.

Option 2 — abstract class and method

class abstract BucketAlgorithm
{
    protected abstract string GetTaskKey(Task task);


    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[GetTaskKey(task)] = th;
        …
    }
}

class SpecificBucketAlgorithm : BucketAlgorithm
{
    protected override string GetTaskKey(Task task) { … }
}

Good for use within a medium scope like just one assembly, where there's no need for better separation of concerns (interfaces from implementation), or where are several non-trivial key-building algorithms required.

Option 3 — decomposed into an interface

interface ITaskKeyGenerator
{
    string GetTaskKey(Task task);
}

class BucketAlgorithm
{
    public BucketAlgorithm(ITaskKeyGenerator taskKeyGenerator)
    {
        this.taskKeyGenerator = taskKeyGenerator;
    }

    private ITaskKeyGenerator taskKeyGenerator;

    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[taskKeyGenerator.GetTaskKey(task)] = th;
        …
    }
}

Good for scenarios where thorough separation of concerns is required or where multiple complex key-building algorithms might exist, or even be provided from the “outside” by users of an API.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文