Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带运算符的泛型值和类型比较器_C#_Generics_Compare - Fatal编程技术网

C# 带运算符的泛型值和类型比较器

C# 带运算符的泛型值和类型比较器,c#,generics,compare,C#,Generics,Compare,我有一个业务逻辑,基于预定义的条件(OperatorType和compare value),验证它是真是假。这里的问题是值是“类型化”的,并且带有运算符(大/小/相等等) 如果ValueType为整数,则需要先将值和比较值转换为Integer,然后基于运算符type,进行比较 我想知道我是否可以有一个通用函数,传递CompareValue,Value,ValueType,OperatorType,并返回true/false using System; using System.Collectio

我有一个业务逻辑,基于预定义的条件(
OperatorType
和compare value),验证它是真是假。这里的问题是值是“类型化”的,并且带有运算符(大/小/相等等)

如果
ValueType
为整数,则需要先将值和比较值转换为
Integer
,然后基于
运算符type
,进行比较

我想知道我是否可以有一个通用函数,传递
CompareValue
Value
ValueType
OperatorType
,并返回true/false

using System;
using System.Collections.Generic;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            var compare1 = 3;
            var foo1 = new Foo { Value = "2", OperatorType = OperatorTypes.GreaterOrEqual, ValueType = ValueTypes.Long };
            //compare compare1 and foo1.Value, output should be false (2 < 3)

            var compare2 = true;
            var foo2 = new Foo { Value = "True", OperatorType = OperatorTypes.Equal, ValueType = ValueTypes.Bool };
            //compare compare2 and foo2.Value, output should be true (true = true)

            var compare3 = DateTime.Parse("2013-03-19 15:00");
            var foo3 = new Foo { Value = "2013-03-19 16:00", OperatorType = OperatorTypes.Less, ValueType = ValueTypes.Date };
            //compare compare3 and foo3.Value, output should be false (2013-03-19 16:00 < 2013-03-19 15:00)
        }
    }

    public enum OperatorTypes : uint
    {
        Equal = 1,
        Greater = 2,
        GreaterOrEqual = 3,
        Less = 4,
        LessOrEqual = 5
    }

    public enum ValueTypes : uint
    {
        None = 0,
        Integer = 1,
        Long = 2,
        Numeric = 3,
        Date = 4,
        Text = 5,
        Bool = 6
    }

    class Foo
    {
        public string Value { get; set; }
        public ValueTypes ValueType { get; set; }
        public OperatorTypes OperatorType { get; set; }
    }
}
使用系统;
使用System.Collections.Generic;
名称空间测试
{
班级计划
{
静态void Main(字符串[]参数)
{
var=1=3;
var foo1=new Foo{Value=“2”,OperatorType=OperatorTypes.GreaterOrEqual,ValueType=ValueTypes.Long};
//比较compare1和foo1。值,输出应为false(2<3)
var compare2=真;
var foo2=new Foo{Value=“True”,OperatorType=OperatorTypes.Equal,ValueType=ValueTypes.Bool};
//比较compare2和foo2.Value,输出应为true(true=true)
var compare3=DateTime.Parse(“2013-03-19 15:00”);
var foo3=new Foo{Value=“2013-03-19 16:00”,OperatorType=OperatorTypes.Less,ValueType=ValueTypes.Date};
//比较compare3和foo3。值,输出应为假(2013-03-19 16:00<2013-03-19 15:00)
}
}
公共枚举运算符类型:uint
{
等于1,
大于等于2,
更大或相等=3,
小于等于4,
出租人相等=5
}
公共枚举值类型:uint
{
无=0,
整数=1,
长=2,
数值=3,
日期=4,
文本=5,
布尔=6
}
福班
{
公共字符串值{get;set;}
public ValueTypes ValueType{get;set;}
公共运算符类型运算符类型{get;set;}
}
}

无需更多的麻烦,您可以开始:

using System;
using System.Diagnostics;
using System.Collections.Generic;

namespace Test
{
    class Program
    {
        public static dynamic CompareVal(Foo logic)
        {
            switch(logic.ValueType)
            {
                case ValueTypes.Integer: return Convert.ToInt32(logic.Value);
                case ValueTypes.Long:    return Convert.ToInt64(logic.Value);
                case ValueTypes.Numeric: return Convert.ToDecimal(logic.Value);
                case ValueTypes.Date:    return Convert.ToDateTime(logic.Value);
                case ValueTypes.Text:    return logic.Value;
                case ValueTypes.Bool:    return Convert.ToBoolean(logic.Value);
            }
            throw new InvalidProgramException("Unsupported ValueType");
        }

        public static bool Evaluate(dynamic val, Foo logic)
        {
            dynamic cmpval = CompareVal(logic);

            switch(logic.OperatorType)
            {
                case OperatorTypes.Equal:          return val == cmpval;
                case OperatorTypes.Greater:        return val >  cmpval;
                case OperatorTypes.GreaterOrEqual: return val >= cmpval;
                case OperatorTypes.Less:           return val <  cmpval;
                case OperatorTypes.LessOrEqual:    return val <= cmpval;
            }

            return false;
        }

        static void Main(string[] args)
        {
            //compare compare1 and foo1.Value, output should be false (2 < 3)
            Debug.Assert(false == Evaluate(3, new Foo 
                        { 
                            Value = "2", 
                            OperatorType = OperatorTypes.GreaterOrEqual, 
                            ValueType = ValueTypes.Long 
                        }));

            //compare compare2 and foo2.Value, output should be true (true = true)
            Debug.Assert(true == Evaluate(true, new Foo 
                        { 
                            Value = "True", 
                            OperatorType = OperatorTypes.Equal, 
                            ValueType = ValueTypes.Bool 
                        }));

            //compare compare3 and foo3.Value, output should be false (2013-03-19 16:00 < 2013-03-19 15:00)
            Debug.Assert(false == Evaluate(DateTime.Parse("2013-03-19 15:00"), new Foo 
                        { 
                            Value = "2013-03-19 16:00", 
                            OperatorType = OperatorTypes.Less, 
                            ValueType = ValueTypes.Date 
                        }));
        }
    }

    public enum OperatorTypes : uint
    {
        Equal = 1,
        Greater = 2,
        GreaterOrEqual = 3,
        Less = 4,
        LessOrEqual = 5
    }

    public enum ValueTypes : uint
    {
        None = 0,
        Integer = 1,
        Long = 2,
        Numeric = 3,
        Date = 4,
        Text = 5,
        Bool = 6
    }

    class Foo
    {
        public string Value { get; set; }
        public ValueTypes ValueType { get; set; }
        public OperatorTypes OperatorType { get; set; }
    }
}
使用系统;
使用系统诊断;
使用System.Collections.Generic;
名称空间测试
{
班级计划
{
公共静态动态比较(Foo逻辑)
{
开关(逻辑.ValueType)
{
case ValueTypes.Integer:返回Convert.ToInt32(logic.Value);
case ValueTypes.Long:返回Convert.ToInt64(logic.Value);
case ValueTypes.Numeric:返回Convert.ToDecimal(logic.Value);
case ValueTypes.Date:返回Convert.ToDateTime(logic.Value);
case ValueTypes.Text:返回逻辑.Value;
case-ValueTypes.Bool:返回Convert.ToBoolean(logic.Value);
}
抛出新的InvalidProgrameException(“不支持的ValueType”);
}
公共静态布尔求值(动态val、Foo逻辑)
{
动态cmpval=比较值(逻辑);
开关(逻辑运算符类型)
{
大小写运算符types.Equal:return val==cmpval;
案例运算符类型。更大:返回值>cmpval;
case OperatorTypes.greaterEqual:return val>=cmpval;
病例操作类型:返回值class程序
{
静态void Main(字符串[]参数)
{
控制台写入线(比较(“123.1”,125.3,(a,b)=>a>b));
Console.WriteLine(比较(“2013年3月19日”,DateTime.Now,(a,b)=>a==b));
}
私有静态布尔比较(字符串值字符串、T值到ompare、函数检查)
{
var asObject=(T)Convert.ChangeType(valueAsString,typeof(T));
if(asObject!=null)
{
返回检查(对象、值到比较);
}
返回false;
}
}

问题是什么?编辑是的,您可以编写这样一个函数。您尝试了什么?@sehe抱歉,我更新了我的问题。我想知道我是否可以有一个常规函数,传递CompareValue、Value、ValueType、OperatorType并返回true/false。@sehe,我尝试使用新的Comparer,但它是一个基类,而不是实现。我尝试了Convert.ChangeType基于ValueType,但它仍然错过了最后一步,即比较。我得到了RuntimeBinderException:运算符“>=”不能应用于“int”和“object”类型的操作数,这与我今天面临的情况类似,因为object无法与value type.Aha进行比较。最好让它也成为动态的。编辑。对,它现在可以工作了,它是有点邪恶,因为它利用了动态,但足够整洁并且完成了任务。@James它比你自己写基本相同的东西要好,所以我不确定它是否真的邪恶。如果有任何问题,你写自己的bug的机会会少一些,如果运行时出现故障,你会得到一致的错误信息。很好,我不知道
Convert.ChangeType
已存在。@Yaugen Vlasau,您的代码无疑是有效的,但它不是针对ValueType进行验证的通用代码。需要附加代码。
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Compare<double>("123.1", 125.3, (a, b) => a > b));
        Console.WriteLine(Compare<DateTime>("19/03/2013", DateTime.Now, (a, b) => a == b));
    }

    private static bool Compare<T>(string valueAsString, T valueToComapare, Func<T,T,bool> check)
    {
        var asObject = (T)Convert.ChangeType(valueAsString, typeof(T));

        if (asObject != null)
        {
            return check(asObject, valueToComapare);
        }

        return false;
    }
}