C# 如何使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

我试图重构一个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;
}
我想去掉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