C# 如何使switch语句更面向对象?
我试图重构一个switch语句,如下所示:C# 如何使switch语句更面向对象?,c#,.net,C#,.net,我试图重构一个switch语句,如下所示: private void Validate(DataTypeEnum dataType, string value, ...) { switch(dataType) { case DataTypeEnum.Number: var typedValue = int.Parse(value); //Validation of typedValue bre
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;
}
}
private void Validate(DataTypeEnum dataType, string value, ...)
{
Validate(value);
}
private void (Decimal value)
{
//Validate
}
private void (DateTime value)
{
//Validate
}
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;
}
我想去掉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;
}
}
private void Validate(DataTypeEnum dataType, string value, ...)
{
Validate(value);
}
private void (Decimal value)
{
//Validate
}
private void (DateTime value)
{
//Validate
}
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;
}
有什么优雅的方法可以解决这个问题吗?private void Validate(T值),其中T:IComparable
private void Validate<T>(T value) where T : IComparable
{
if(value is Number)
{
}
if(value is Decimal)
{
}
if(value is DateTime)
{
}
}
{
如果(值为数字)
{
}
if(值为十进制)
{
}
if(值为DateTime)
{
}
}
使用多态性
例如:
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();
}
公共类数据类型
{
公共虚拟void Validate()
{
WriteLine(“执行基类验证任务”);
}
}
类Foo:数据类型
{
公共覆盖无效验证()
{
//验证foo的代码。。。
Console.WriteLine(“验证一个foo”);
}
}
类栏:数据类型
{
公共覆盖无效验证()
{
//验证条形图的代码。。。
Console.WriteLine(“验证条”);
}
}
列表数据类型=新列表();
添加(新的Foo());
添加(新的Barr());
foreach(数据类型中的数据类型s)
{
s、 验证();
}
首先,我将从实现简单的验证界面开始:
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;
}
var\u validators=新字典//通过DI注入
{
{DataTypeEnum.Number,新的NumberValidator()},
{DataTypeEnum.DateTime,新的DateTimeValidator()},
{DataTypeEnum.String,新的StringValidator()}
};
......
私有布尔验证(DataTypeEnum数据类型、对象值等)
{
if(_validators.ContainsKey(数据类型))
{
返回_validators[dataType].Validate(值);
}
返回false;
}
像这样的东西怎么样:
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;
}
}
private void Validate(DataTypeEnum dataType, string value, ...)
{
Validate(value);
}
private void (Decimal value)
{
//Validate
}
private void (DateTime value)
{
//Validate
}
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;
}
如果传入的值是数字、十进制或DATE时间,它将运行适当的方法,否则它将简单地返回.
以添加到此,尽管有些人可能认为这不是OOP,但可以使用<代码>动态< /COD>重载来处理:
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
基本上,这与通常的重载解析相同,但它是在运行时执行的,具体取决于ValidateAny
中val
的运行时类型
例如:
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
/开关。即使这样,它也可以为您节省大量时间。创建一个以DataTypeEnum为键、Action为值的字典。然后按键从字典中获取值并调用操作
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);
}
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
}
//...
private readonly Dictionary Validator=新字典
{
{DataTypeEnum.Number,()=>Validate(Convert.ToDouble((string)value))},
{DataTypeEnum.Decimal,()=>Validate(Convert.ToDecimal((字符串)值))},
{DataTypeEnum.DateTime,()=>Validate(Convert.ToDateTime((字符串)值))},
// ...
}
私有void验证(DataTypeEnum数据类型、对象值等)
{
验证程序[dataType]();//获取并调用该操作
}
私有无效验证(十进制值)
{
//证实
}
私有void验证(日期时间值)
{
//证实
}
//...
这里的操作是不带参数的Void委托。它会将值转换为合适的格式并调用Validate方法。为什么不私有void Validate(IComparable value)
?因为这样您就不会访问运行时类型的值,您将把它转换为IComparable
方法,所以值为Number
将返回false
。否。即使引用类型为IComparable,对象仍然是一个数字。这与数据验证有什么关系?问题不在于行为,而在于数据。@Fabjan,别这样。最初的问题不是关于验证。它只是以此为例。这个答案使用了另一个例子。我建议对这些例子进行编辑。也许这是一个好的设计,但我认为这不是答案。OP将字符串作为对象发送到验证。但我看不出对象值在这里有什么用处。我知道你可以像这样加入名单。。。但是你不能给出这样的建议,因为你不知道在Validate method.OP使用enum DataTypeEnum not类之前发生了什么。它将如何验证int、string、bool等类型?只有当我们使用用户类时,这才是一个很好的答案。这个问题将对您有所帮助。597:在这一点上,我没有类型化的对象,我只是有一个需要解析的字符串和一些类型枚举。那么除了switch
语句之外,您为什么还要处理其他任何事情呢?如果你想要面向对象的,你需要真正的对象。方法末尾的返回是redundanttrue,但是它让我更容易阅读,而且不会有什么坏处。你也可以用一个实际的方法来代替它,当传递的值不是预期的数据类型时,用它来处理时间。包括不必要的代码使我(在你找到另一份工作后会阅读你的代码的人)想知道你为什么把它放在那里。这花了我很多时间,我本可以花在做别的事情上的。我写代码是为了好玩,你取代我的工作的机会很大。因为一行多余的行在上下文中可能被视为占位符,所以不需要侮辱。那么,value
当时是什么意思呢?好吧,现在它更有意义了,但它仍然像地狱一样脆弱。如何防止人们传入不兼容的验证器
和值
实例?您需要采取下一步来反射代码。值应成为IValidator的属性。IValidator应该成为泛型类型。您缺少一个关键点-您的示例中没有IValidator
,因此代码将无法编译。C#没有Java的IGeneric
。很好,upda