避免if / else的最佳实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了避免if / else的最佳实现相关的知识,希望对你有一定的参考价值。

我正在为公司度假计划,并指定了在特定假日允许的时间。

我使用了带有抽象方法的Abstract类:

public abstract class Abstract : TimeLength
{
    public AbstractTest(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(startDate, endDate, "")
    {
        TypeOfHoliday = typeOfHoliday;
        Employee = employee;
        EmployeeCode = employeeCode;
    }
    public string EmployeeCode { get; set; }
    public string Employee { get; set; }
    public string TypeOfHoliday { get; set; }

    public abstract bool HolidayValidation(string typeOfHoliday);
}

而且我使用了像这两个抽象类一样固有的多个类:

class MarriageVacation : Abstract
{
    public MarriageVacation(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(employeeCode, employee, typeOfHoliday, startDate, endDate)
    {
    }

    public override bool HolidayValidation(string typeOfHoliday)
    {
        if (Days() > (int)Holiday.MarriageVacation)
        {
            MessageBox.Show("Marriage Vacation Can only be 5 Days");
            return false;
        }
        else
            return true;
    }
}


class Bereavement : Abstract
{
    public Bereavement(string employeeCode, string employee, string typeOfHoliday, DateTime startDate, DateTime endDate) : base(employeeCode, employee, typeOfHoliday, startDate, endDate)
    {
    }

    public override bool HolidayValidation(string typeOfHoliday)
    {
        if (Days() > (int)Holiday.Bereavement)
        {
            MessageBox.Show("Bereavement Can only be 5 Days");
            return false;
        }
        else
            return true;
    }
}

我在假期使用Enummain中,我要根据用户的选择进行注册:

List<Abstract> holiday = new List<Abstract>();
if(CmbTypeHolidays.Text == Holiday.Bereavement.ToString())
        {
            var holid = new Bereavement(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], CmbTypeHolidays.Text, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));

            if (holid.HolidayValidation(CmbTypeHolidays.Text))
            {
                holiday.Add(holid);
                var bindingList = new BindingList<Abstract>(holiday);
                dataGridHolidays.DataSource = bindingList;
                controlPanelHolidays.Visible = false;
            }
        }
        else if (CmbTypeHolidays.Text == Holiday.MarriageVacation.ToString())
        {
            var holid = new MarriageVacation(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], CmbTypeHolidays.Text, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));

            if (holid.HolidayValidation(CmbTypeHolidays.Text))
            {
                holiday.Add(holid);
                var bindingList = new BindingList<Abstract>(holiday);
                dataGridHolidays.DataSource = bindingList;
                controlPanelHolidays.Visible = false;
            }
        }

我想知道一种更好的方法来实现此解决方案,或者只是更改将数据插入抽象List的代码

答案

您将需要建立一个将假期类型名称映射到实现它的类的工厂:

private class HolidayConstructorArgs {
    public string EmployeeCode {get;set;}
    public string Employee {get;set;}
    public string TypeOfHoliday {get;set;}
    public DateTime From {get;set;}
    public DateTime To {get;set;}
}

private static readonly IDictionary<string,Func<HolidayConstructorArgs,AbstractHoliday>> HolidayByTypeCode =
    new Dictionary<string,Func<HolidayConstructorArgs,AbstractHoliday>> {
        [$"{Holiday.Bereavement}"] = a => new Bereavement(a.EmployeeCode, a.Employee, a.TypeOfHoliday, a.From, a.To)
    ,   [$"{Holiday.MarriageVacation}"] = a => new MarriageVacation(a.EmployeeCode, a.Employee, a.TypeOfHoliday, a.From, a.To)
    };

现在您可以从字典中获取工厂,并使用它来实例化对象:

if (HolidayByTypeCode.TryGetValue(CmbTypeHolidays.Text, out var factory)) {
    // This is where the "magic" happens:
    // Func<> will invoke the appropriate constructor without a conditional
    var holid = factory(
        new HolidayConstructorArgs {
            EmployeeCode = CmbEmpHolidays.Text.Split('-')[0]
        ,   Employee = CmbEmpHolidays.Text.Split('-')[1]
        ,   TypeOfHoliday = CmbTypeHolidays.Text
        ,   From = Convert.ToDateTime(StartDateHolidays.Value)
        ,   To = Convert.ToDateTime(EndDateHolidays.Value)
        }
    );
    // ... The rest of your code remains the same
}
另一答案

我根据关于这个问题的答案进行了更改,这是Main class(Abstract):

public class AbstractTest : TimeLength
{
    public AbstractTest(string employeeCode, string employee, Holiday typeOfHoliday, DateTime startDate, DateTime endDate) : base(startDate, endDate, "")
    {
        TypeOfHoliday = typeOfHoliday;
        Employee = employee;
        EmployeeCode = employeeCode;
    }
    public string EmployeeCode { get; set; }
    public string Employee { get; set; }
    public Holiday TypeOfHoliday { get; set; }

    public bool HolidayValidation(Holiday typeOfHoliday)
    {
        return Days() > (int)typeOfHoliday;
    }
}

并且在Main中,我改为::>

Holiday MyStatus = (Holiday)Enum.Parse(typeof(Holiday), CmbTypeHolidays.Text, true);
        var holid = new AbstractTest(CmbEmpHolidays.Text.Split('-')[0], CmbEmpHolidays.Text.Split('-')[1], MyStatus, Convert.ToDateTime(StartDateHolidays.Value), Convert.ToDateTime(EndDateHolidays.Value));

        if (!holid.HolidayValidation(MyStatus))
        {
            holiday.Add(holid);
            var bindingList = new BindingList<AbstractTest>(holiday);
            dataGridHolidays.DataSource = bindingList;
            controlPanelHolidays.Visible = false;
        }
        else
        {
            MessageBox.Show($"{holid.TypeOfHoliday} Cant be more than {(int)MyStatus} Days");
        }

对于[Holiday

,我使用了[[Holiday类型,因此更易于使用,用户可以选择将其转换为Enum Holiday] >
您对HolidayValidation具有相同(几乎)的实现,而没有使用typeOfHoliday
另一答案
您对HolidayValidation具有相同(几乎)的实现,而没有使用typeOfHoliday

以上是关于避免if / else的最佳实现的主要内容,如果未能解决你的问题,请参考以下文章

避免android片段中内存泄漏的最佳方法是啥

20个简洁的 JS 代码片段

如何避免一连串的if else

ifelse语句if条件可以为空吗

满屏的if-else,看我怎么消灭你!

微信开发解决if...else..的臃肿