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;
}
}