如何使switch语句更面向对象?

时间:2015-07-09 14:08:30

标签: c# .net

我正在尝试重构这样的switch语句:

private void Validate(DataTypeEnum dataType, string value, ...)
{
    switch(dataType)
    {
        case DataTypeEnum.Number:
            var typedValue = int.Parse(value);
            //Validation of typedValue
            break;
        case DataTypeEnum.Decimal:
            var typedValue = Decimal.Parse(value);
            //Validation of typedValue
            break;
        case DataTypeEnum.DateTime:
            var typedValue = DateTime.Parse(value);
            //Validation of typedValue
            break;
    }
}

我想摆脱switch语句,并以某种方式用更面向对象的构造替换它。有什么建议吗?

我的理想是这样的:

private void Validate(DataTypeEnum dataType, string value, ...)
{
    Validate(value);
}
private void (Decimal value)
{
    //Validate
}
private void (DateTime value)
{
    //Validate
}

有没有优雅的方法来解决这个问题?

7 个答案:

答案 0 :(得分:6)

使用多态。

示例:

public class DataType
{
    public virtual void Validate()
    {
        Console.WriteLine("Performing base class validation tasks");
    }
}

class Foo : DataType
{
    public override void Validate()
    {
        // Code to validate a foo...
        Console.WriteLine("Validating a foo");
    }
}
class Bar : DataType
{
    public override void Validate()
    {
        // Code to validate a bar...
        Console.WriteLine("Validating a bar");
    }
}


List<DataType> datatypes = new List<DataType>();
datatypes.Add(new Foo());
datatypes.Add(new Barr());

foreach (DataType s in datatypes)
{
    s.Validate();
}

答案 1 :(得分:5)

要添加到此,虽然有些人可能会认为这不是OOP,但您可以使用dynamic重载来处理此问题:

public bool ValidateAny(dynamic val)
{
  return Validate(val);
}

private bool Validate(string val) { ... }
private bool Validate(int val) { ... }
private bool Validate(decimal val) { ... }

private bool Validate(object val) { ... } // This is the fallback

基本上,这与通常的重载分辨率相同,但它在运行时执行,具体取决于valValidateAny的运行时类型。

例如:

ValidateAny(3); // Uses the int overload
ValidateAny((object)3); // Uses the int overload as well - dynamic handles the unboxing
ValidateAny(3M); // Uses the decimal overload
ValidateAny(3.ToString()); // Uses the string overload
ValidateAny(3f); // Uses the object overload, since there's no better match

这是非常强大的,只要您只需要对不同的类型进行不同的验证。如果您还有其他注意事项,则必须在某种程度上返回if / switch。尽管如此,它可以为你节省很多时间。

答案 2 :(得分:1)

首先,我首先要实现简单的验证接口:

public interface IValidator
{
    bool Validate(object value);
}

然后数字验证器可能如下所示:

public class NumberValidator : IValidator
{
    public bool Validate(object value)
    {
        return (int) value > 0;
    }
}

最后一步用字典替换你的开关:

 var _validators = new Dictionary<DataTypeEnum, IValidator> // injected via DI
 {
     { DataTypeEnum.Number, new NumberValidator() },
     { DataTypeEnum.DateTime, new DateTimeValidator() },
     { DataTypeEnum.String, new StringValidator() }
 };

 ......

 private bool Validate(DataTypeEnum dataType, object value, ...)
 {
     if (_validators.ContainsKey(dataType))
     {
        return _validators[dataType].Validate(value);
     }

     return false;
 }

答案 3 :(得分:0)

    public interface IValidator
    {
        void Validate(object value);
    }

    public class NumberValidator : IValidator
    {
        public void Validate(object value)
        {
            //implementation
        }
    }

    public class DecimalValidator : IValidator
    {
        public void Validate(object value)
        {
            //implementation
        }
    }

    public class DatetimeValidator : IValidator
    {
        public void Validate(object value)
        {
            //implementation
        }
    }

    private void Validate(IValidator validator, object value)
    {
        validator.Validate(value);
    }

答案 4 :(得分:0)

创建一个字典,其中DataTypeEnum为Key,Action为Value。然后按键从字典中获取值并调用操作。

private readonly Dictionary<DataTypeEnum , Action > Validator = new Dictionary<DataTypeEnum , Action >
        {
            { DataTypeEnum.Number, () => Validate(Convert.ToDouble((string)value)) },
            { DataTypeEnum.Decimal, () => Validate(Convert.ToDecimal((string)value)) },
            { DataTypeEnum.DateTime, () => Validate(Convert.ToDateTime((string)value)) },
            // ...
        }

private void Validate(DataTypeEnum dataType, object value, ...)
{
    Validator[dataType](); // Gets the Action and Invokes it
}

private void Validate (Decimal value)
{
    //Validate
}
private void Validate (DateTime value)
{
    //Validate
}
//...

这里的Action是Void委托,不带参数。它会将值转换为合适的格式并调用Validate Method。

答案 5 :(得分:-5)

private void Validate<T>(T value) where T : IComparable
{
    if(value is Number)
    {

    }
    if(value is Decimal)
    {

    }
    if(value is DateTime)
    {

    }
}

答案 6 :(得分:-6)

这样的事情怎么样:

private void Validate(object value, ...)
{
    if(Reference.Equals(null, value)
        return;

    if(value is Number)
    {

    }
    else if(value is Decimal)
    {

    }
    else if (value is DateTime)
    {

    }
    else return;
}

如果传入的值是Number,Decimal或DateTime,它将运行适当的方法,否则它只会返回。