删除if语句并使其更具可读性

时间:2017-11-30 16:20:15

标签: c# design-patterns

您好想知道是否有更好的方法来删除其他if语句并使用策略模式。 任何想法?

public async Task<TResponse> HandleResponseAsync<TRequest, TResponse>(TRequest item)
    where TResponse : class, new()
{
    TResponse result = default(TResponse);
    Type currentResponseType = typeof(TResponse);   

    if (currentResponseType == typeof(MyResponseA))
    {
        result = //dosomething
    }
    else if (currentResponseType == typeof(MyResponseB))
    { 
        result = //dosomething
    }
    else if (currentResponseType == typeof(MyResponseC))
    {
        result = //dosomething
    }

    return result;
}

3 个答案:

答案 0 :(得分:7)

在泛型方法中使用特定的子类是一种非常危险的方法,因为它通过将您锁定到泛型方法内的类列表来限制未来的灵活性。它还抛弃了使其成为通用方法所能获得的大部分优势。

由于您已经需要无参数构造函数,因此一种方法是为您的TResponse提供一个接口,并使用该接口回调实例以获得正确的结果:

interface IResponse {
    void Configure(); // Use custom parameters if necessary
}

public async Task<TResponse> HandleResponseAsync<TRequest, TResponse>(TRequest item)  where TResponse : class, new(), IResponse {
    TResponse result = new TResponse();
    result.Configure(...);
}

现在来自if-then-else块的代码将进入相应Configure实现的IResponse方法:

class MyResponseA : IResponse {
    public MyResponseA() {}
    public void Configure() {
        // dosomething from the first IF
    }
}
class MyResponseB : IResponse {
    public MyResponseB() {}
    public void Configure() {
        // dosomething from the second IF
    }
}

注意:如果不同的实例需要传递HandleResponseAsync的不同信息,事情可能会变得棘手。在这种情况下,您还应该创建一个对象,其中包含任何实现可能需要的所有信息,以便完成其Configure方法。

答案 1 :(得分:5)

如果你打开泛型的类型,你可能做错了。泛型应该泛型。您编写的代码不是通用的,它的非常脆弱,而且泛型使它更多,而不是更简单。

在这里,让我为你重写一下:

if (currentResponseType == typeof(MyResponseA))
    return (TResponse) HandleResponseA(item);
else if (currentResponseType == typeof(MyResponseB))
    return (TResponse) HandleResponseB(item);
else if (currentResponseType == typeof(MyResponseC))
    return (TResponse) HandleResponseC(item);

如果通过该方法有三种可能的代码路径,那么只需编写三种方法HandleResponseAHandleResponseBHandleResponseC即可。 这就是你已经做过的事情,你只需将每个方法的主体作为if的主体。这里没有储蓄使它们成为一种方法;你刚刚做了一个脆弱的,过于复杂的方法。现在我们已经重构了您的方法,我们发现我们可以完全删除该方法,只需直接调用适当的处理程序

另外,考虑一下你的不良来电者!在通话网站上,没有令人信服的理由倾向于HandleResponseAsync<Giraffe, MyResponseB>(giraffe)更好HandleResponseB(giraffe);如果有三种方法而不是一种方法,呼叫站点更短,更清晰,更安全。

此外,如果此处提供的服务100%取决于响应对象的类型,那么为什么这不是响应对象的关注?为什么呼叫网站实际上不是MyResponseB.Handle(giraffe)?方法可以是响应类型的静态方法。如果您要编写三个方法体,每种类型一个,那么将它们放在该类型上

答案 2 :(得分:1)

c#7 中,您可以使用switch

       var response = new TRsponse();
        switch (response)
        {
            case MYResponseB b:
                break;

            case MYResponse a:
                break;

         }
  

我们正在推广switch语句,以便:1。您可以打开任何类型(不仅仅是原始类型)2.Patterns可用于case子句3.Case子句可以有其他条件

这是c#7中的新功能:

https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/