我正在尝试重构这样的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
}
有没有优雅的方法来解决这个问题?
答案 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
基本上,这与通常的重载分辨率相同,但它在运行时执行,具体取决于val
中ValidateAny
的运行时类型。
例如:
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,它将运行适当的方法,否则它只会返回。