【问题标题】:Is there a way to pass a method into another method in c# and what's the best way to do it?有没有办法将一个方法传递给 c# 中的另一个方法,最好的方法是什么?
【发布时间】:2019-12-14 22:21:03
【问题描述】:

我正在努力让我的代码保持干燥。我有 5 种方法具有相同的大量代码,但我不想多次编写它们。以下是 2 个示例方法。我想知道如何将其合并为 1 个通用方法。这是最好的方法吗?

public async Task<PlaylistListResponse> GetPlaylistsFromChannel(string channelID, bool forceRefresh = false)
{
    string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
    PlaylistListResponse results = default;

    if(forceRefresh != true)
    {
        results = GetCached<PlaylistListResponse>(barrelURL);
    }
    else
    {
        try
        {
            if (object.Equals(results, default(PlaylistListResponse)))
            {
                var playlistFromChannelRequest = youtubeService.Playlists.List("id");
                playlistFromChannelRequest.ChannelId = channelID;
                playlistFromChannelRequest.MaxResults = 50;
                results = await playlistFromChannelRequest.ExecuteAsync();
                Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
            }

            return results;
        }
        catch (Exception ex)
        {
            Crashes.TrackError(ex);
        }
    }

    return results;
}

public async Task<PlaylistListResponse> GetPlaylistsFromChannel(string channelID, bool forceRefresh = false)
{
    string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
    PlaylistListResponse results = default;

    if (forceRefresh != true)
    {
        results = GetCached<PlaylistListResponse>(barrelURL);
    }
    else
    {
        try
        {
            if (object.Equals(results, default(PlaylistListResponse)))
            {
                var videosFromPlaylistRequest = youtubeService.PlaylistItems.List("snippet");
                videosFromPlaylistRequest.PlaylistId = playlistID;
                videosFromPlaylistRequest.MaxResults = 50;

                results = await videosFromPlaylistRequest.ExecuteAsync();
                Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
            }

            return results;
        }
        catch (Exception ex)
        {
            Crashes.TrackError(ex);
        }
    }

    return results;
}

我尝试创建一个通用方法,但找不到对其进行更改的方法,因为我不想要大量的 if 语句。

public async Task<T> GetAsync<T>(string barrelURL, int days = 7, bool forceRefresh = false)
{
    results = default(T);

    if (!CrossConnectivity.Current.IsConnected)
        results = Barrel.Current.Get<T>(barrelURL);

    if (!forceRefresh && !Barrel.Current.IsExpired(barrelURL))
        results = Barrel.Current.Get<T>(barrelURL);

    try
    {
        if (object.Equals(results, default(T)))
        {
            //myMethodsCode??
            Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(days));
        }

        return results;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Unable to get information from server {ex}");
    }
}

【问题讨论】:

    标签: c# generics delegates .net-standard


    【解决方案1】:

    此问题的一个可能解决方案是创建一个通用方法并将代表不同部分的委托传递给它。

    public async Task<T> GetFromChannel<T>(
        string channelID,
        Func<Task<T>> resultGetter,
        bool forceRefresh = false)
    {
        string barrelURL = "GetPlaylistsFromChannel" + channelID.Trim();
        T results = default;
    
        if (forceRefresh != true)
        {
            results = GetCached<T>(barrelURL);
        }
        else
        {
            try
            {
                if (object.Equals(results, default(T)))
                {
                    results = await resultGetter();
                    Barrel.Current.Add(barrelURL, results, TimeSpan.FromDays(30));
                }
    
                return results;
            }
            catch (Exception ex)
            {
                Crashes.TrackError(ex);
            }
        }
    
        return results;
    }
    

    然后您可以使用其他方法或 lambda 表达式插入不同的部分,例如:

    public Task<PlaylistListResponse> GetPlaylistsFromChannel(
        string channelID,
        bool forceRefresh = false)
    {
        return GetFromChannel<PlaylistListResponse>(
            channelID,
            async () =>
            {
                var videosFromPlaylistRequest = youtubeService.PlaylistItems.List("snippet");
                videosFromPlaylistRequest.PlaylistId = playlistID;
                videosFromPlaylistRequest.MaxResults = 50;
    
                return await videosFromPlaylistRequest.ExecuteAsync();
            },
            forceRefresh);
    }
    

    【讨论】:

    • 感谢您的回答。这是最有效的方法吗?
    • @RyanGaudion 如果您的意思是在速度和/或内存效率方面高效,那么我真的不知道。这显然比直接编写 5 个不同的方法效率要低一些,因为它涉及更多的方法调用,并且对于每个委托都有一个必须分配的实例。但我会说这是速度和内存的一个非常微不足道的变化。如果您的意思是从可维护性的角度(DRY 等)高效,那么它是主观的,但对我而言,它是相当可维护的。
    • 谢谢你,它真的很有帮助!
    • 请您查看我原来的问题。如果它需要改进,那么请你建议如何改进它,如果没有,请你支持它。谢谢
    • @RyanGaudion 我已经修复了您问题中的代码格式。除此之外,我想没关系:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 2016-12-21
    • 2014-10-07
    • 2014-01-05
    • 2016-02-13
    • 2019-02-15
    相关资源
    最近更新 更多