C# 避免其他情况

C# 避免其他情况,c#,oop,solid-principles,open-closed-principle,java,C#,Oop,Solid Principles,Open Closed Principle,Java,我想重构以下代码以避免if…else,这样我就不必在每次出现新的调查类型时都更改方法(开放/封闭原则)。下面是我正在考虑重构的一段代码: if (surveyType == SurveySubType.Anonymous) { DoSomething(param1, param2, param3); } else if (surveyType == SurveySubType.Invitational) { DoSomething(param1); } else if (sur

我想重构以下代码以避免if…else,这样我就不必在每次出现新的调查类型时都更改方法(开放/封闭原则)。下面是我正在考虑重构的一段代码:

if (surveyType == SurveySubType.Anonymous)
{
    DoSomething(param1, param2, param3);

}
else if (surveyType == SurveySubType.Invitational)
{
    DoSomething(param1);
}
else if (surveyType == SurveySubType.ReturnLater)
{    
    DoSomething(param1);
}
为了解决这个问题,我添加了以下类:

    public abstract class BaseSurvey
{
            public string BuildSurveyTitle()
            {
             ...doing something here
            }

    public abstract void DoSomething(int? param1,int?  param2,int?  param3);
}
public class InvitationalSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {
    //I don't need param2 and param3 here

    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {
    //I don't need param2 and param3 here

    }
}


public class AnonymousSurvey: BaseSurvey
{
    public override void DoSomething(int? param1,int?  param2,int?  param3)
    {

    //I need param2 and param3 here
    //do something
    }

}
这就是我的代码的结局:

var survey = SurveyFactory.Create();
survey.DoSomething(param1,param2,param3);

我的问题是,避免将param2和param3传递给InvitationSurvey和ReturnLaterSurvey类有什么好处?

您发布的代码不是或。无论如何,听起来你想要一个。

你可以有另一个抽象类扩展
BaseSurvey
,它
InvitationalSurvey
ReturnLaterSurvey
都扩展了。这个抽象类可以通过调用自己的抽象方法
DoSomething(param1,param2,param3)
来实现
DoSomething(param1)
,这
InvitationalSurvey
returnlatersvey
可以扩展
DoSomething(param1,param2,param3)


为什么不添加一个重载呢

doSometing(Param1){
 doSomething(Param1, null, null)
}

了解参数类型会有所帮助。如果它们都是相同的,那么您至少可以在C#中使用
params
关键字并根据需要发送尽可能多的参数。如果没有,那么您可能希望传递一个参数字典,然后让实现类将对象强制转换为正确的类型

public abstract class BaseSurvey
{
    public abstract void DoSomething(params string[] parameters);
}

public abstract class BaseSurvey
{
    public abstract void DoSomething(Dictionary<string,object> parameters);
}


这似乎是
过载的情况
,但已经有人建议了。作为一种替代方法,为什么不这样做呢,这意味着为参数指定一个默认值使其成为可选的。看看下面的例子

我演示了一个整数类型,您可以更改该类型并使您的默认值最适合


如果
param2
param3
匿名调查
的具体要求,则它们不应是接口的一部分,而是具体类别的一部分:

public abstract class BaseSurvey
{
    public abstract void DoSomething(param1);
}

public class InvitationalSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class AnonymousSurvey: BaseSurvey
{
    private readonly object param2;
    private readonly object param3

    public AnonymousSurvey(param2, param3)
    {
        this.param2 = param2;
        this.param3 = param3;
    }

    public void DoSomething(param1)
    {
        // use this.param2 and this.param3 here
    }
}

我能想到的最好办法就是为参数添加一个类似的类结构。。。换句话说,创建一个类似BaseSurveyArguments的基类,并根据需要对其进行扩展。不过不是很优雅。看看这个,我很高兴Delphi有了
case
开关。在C#中没有这样的替代方法吗?
C#
确实有
case
语句,在中也提到了该语句。也许有一些聪明的方法可以使用委托或实体引用使其更加流畅,尽管我自己还没有体验过。我也认为
switch
和默认参数一起使用是一种解决方案。在Python中,可以为所有参数指定默认值,并提供更新参数的列表。另一个问题是,如果只有一种
DoSomething
方法。为什么不
ProcessLateSurvey
ProcessAnonSurvey
etc.方法?这个问题似乎离题了,因为它是关于。你的个人资料图片背后隐藏着什么样的宣传?我认为@nurettin暗示你可能是在通过你的avatar@DavidWallace如果你想直接向网站上的人提问,您可以使用@符号,以便他们获得警报。假设这是针对我的,我显然是在暗示你在使用一张宣传画,并询问它的含义。@nurettin我认为你非常清楚它的含义,你只是想挑起一场战斗。我不认为Stack Overflow是合适的论坛,是吗?@DavidWallace我同意,Stack Overflow不是你宣传的地方。我们有reddit。DoSomething不应该被提取为接口,然后你可以使用依赖注入吗?你可以这样做。这是我首选的设计方法,但正如前面所述,
BaseSurvey
是一种纯粹的抽象类型,因此从客户的角度来看,它在组成上相当于一个接口。@MarkSeemann您能给我一个客户如何调用DoSomething的示例吗?需要对匿名调查进行类型检查以通过param2和param3权限?何时创建
邀请调查
返回后调查
匿名调查
对象?谁拥有
param2
param3
值?@MarkSeemann正如我上面所示,工厂方法创建对象。param2和param3仅与AnonymousSurvey类相关。然后,您需要再次引入if…else类型检查来确定要调用哪个工厂方法。@fahmi-没有办法解决这个问题。但它确实在创作代码中进行了本地化。
var survey = surveyFactory.CreateAnonymousSurvey(param1, param2, param3);
survey.DoSomething();
var survey = surveyFactory.CreateReturnLaterSurvey(param1);
survey.DoSomething();
using System;

public class Test
{
    public static void Main()
    {
        // your code goes here
        InvitationalSurvey iservey = new InvitationalSurvey();
        iservey.DoSomething(1, 1, 1);
        iservey.DoSomething(1);
    }
}

public abstract class BaseSurvey
{
     
}
public class InvitationalSurvey: BaseSurvey
{
    public void DoSomething(int param1, int param2 = 0, int param3 = 0)
    {
    //I don't need param2 and param3 here
    Console.WriteLine(string.Format("{0},{1},{2}",param1, param2, param3));
    }
}
public abstract class BaseSurvey
{
    public abstract void DoSomething(param1);
}

public class InvitationalSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class ReturnLaterSurvey: BaseSurvey
{
    public void DoSomething(param1)
    {
    }
}


public class AnonymousSurvey: BaseSurvey
{
    private readonly object param2;
    private readonly object param3

    public AnonymousSurvey(param2, param3)
    {
        this.param2 = param2;
        this.param3 = param3;
    }

    public void DoSomething(param1)
    {
        // use this.param2 and this.param3 here
    }
}