我有自己的动态对象,它必须与原始类型相比较。我为所有要比较的类型定义了隐式强制转换运算符。对于大多数原语类型(如int、short、bool、十进制实现),这种类型的强制转换为空版本对于成功地进行比较是足够的,但对于DateTime则不够。我是否错过了DateTime和十进制之间的显著差异,还是在动态实现中出现了错误?
class MyDynamic : DynamicObject
{
public static implicit operator decimal?(MyDynamic nullable)
{
return null;
}
public static implicit operator DateTime?(MyDynamic x)
{
return null;
}
//public static implicit operator DateTime(MyDynamic x)
//{
// return DateTime.MinValue;
//}
}
[Fact]
public void FactMethodName()
{
dynamic my = new MyDynamic();
dynamic date = DateTime.Now;
dynamic dec = 1m;
Assert.False(dec == my);
// throws
Assert.False(date == my);
}如果未定义隐式强制转换,则错误消息为:
System.InvalidOperationExceptionThe operands for operator 'Equal' do not match the parameters of method 'op_Equality'.堆栈跟踪是:
System.InvalidOperationExceptionThe operands for operator 'Equal' do not match the parameters of method 'op_Equality'.
at System.Linq.Expressions.Expression.GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, Boolean liftToNull)
at System.Linq.Expressions.Expression.Equal(Expression left, Expression right, Boolean liftToNull, MethodInfo method)
at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateUserDefinedBinaryOperator(EXPRCALL pExpr)
at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.VisitCALL(EXPRCALL pExpr)
at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Dispatch(EXPR pExpr)
at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Visit(EXPR pExpr)
at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.GenerateLambda(EXPRCALL pExpr)
at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.VisitCALL(EXPRCALL pExpr)
at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Dispatch(EXPR pExpr)
at Microsoft.CSharp.RuntimeBinder.Semantics.ExprVisitorBase.Visit(EXPR pExpr)
at Microsoft.CSharp.RuntimeBinder.ExpressionTreeCallRewriter.Rewrite(TypeManager typeManager, EXPR pExpr, IEnumerable`1 listOfParameters)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.CreateExpressionTreeFromResult(IEnumerable`1 parameters, ArgumentObject[] arguments, Scope pScope, EXPR pResult)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, ref DynamicMetaObject deferredBinding)
at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, ref DynamicMetaObject deferredBinding)
at Microsoft.CSharp.RuntimeBinder.BinderHelper.Bind(DynamicMetaObjectBinder action, RuntimeBinder binder, IEnumerable`1 args, IEnumerable`1 arginfos, DynamicMetaObject onBindingError)
at Microsoft.CSharp.RuntimeBinder.CSharpBinaryOperationBinder.FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg, DynamicMetaObject errorSuggestion)
at System.Dynamic.BinaryOperationBinder.FallbackBinaryOperation(DynamicMetaObject target, DynamicMetaObject arg)
at System.Dynamic.DynamicMetaObject.BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
at System.Dynamic.BinaryOperationBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
at System.Runtime.CompilerServices.CallSiteBinder.BindCore(CallSite`1 site, Object[] args)
at System.Dynamic.UpdateDelegates.UpdateAndExecute2<T0,T1,TRet>(CallSite site, T0 arg0, T1 arg1)在大多数情况下,我的自定义动态应该几乎是空的,所以转换到值类型是不需要的。
发布于 2015-01-25 15:29:29
定义操作符==使代码更简单。
public static bool operator ==(MyDynamic lhs, object rhs)
{
if (rhs is MyDynamic)
return lhs.Equals(rhs);
else
return false;
}
public static bool operator !=(MyDynamic lhs, object rhs)
{
if (rhs is MyDynamic)
return !lhs.Equals(rhs);
else
return true;
}
public static bool operator ==(object lhs, MyDynamic rhs)
{
if (lhs is MyDynamic)
return lhs.Equals(rhs);
else
return false;
}
public static bool operator !=(object lhs, MyDynamic rhs)
{
if (lhs is MyDynamic)
return !lhs.Equals(rhs);
else
return true;
}编辑i显式实现(MyDynamic ==对象)和(object == MyDynamic)。因为覆盖TryBinaryOperation()无法捕获(对象== MyDynamic)的情况。
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
{
if (binder.Operation == System.Linq.Expressions.ExpressionType.Equal) { ... }
return base.TryBinaryOperation(binder, arg, out result);
}https://stackoverflow.com/questions/27943780
复制相似问题