首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DynamicObject的加法运算

DynamicObject的加法运算
EN

Stack Overflow用户
提问于 2016-01-10 18:48:27
回答 1查看 627关注 0票数 0

我有一个DynamicObject子类,其中实现了几个隐式运算符(用于自动转换),并覆盖了一些TryOperationType方法。

当我尝试使用该类型的对象进行add(+)操作时,我会得到一个异常(问题底部的异常)。

代码语言:javascript
复制
...
var d = GetDynamicObject();
int result = d + 1;
...

一个我认为有助于解决这个问题的答案,是这个吗?。描述的行为是正确的,但是我的动态对象定义了几个静态隐式运算符,我认为问题在于字符串。当我为字符串定义隐式运算符时,que add(+)操作会引发异常。我可以通过堆栈跟踪观察到,问题可能是他不能绑定操作符,我开始认为这是因为某种添加/连接混淆。

我简化了我的代码,并编写了这个测试,我认为它描述了这种情况。当我为字符串注释隐式运算符时,每件事都很有效。

我做错了什么吗?有什么方法我也需要重写吗?有什么想法吗?

代码语言:javascript
复制
public class Program
{
    static void Main(string[] args)
    {
        try
        {
            var d = GetDynamicObject();
            int result = d + 1;
            Console.WriteLine("OK: " + result);
        }
        catch (Exception)
        {
            Console.WriteLine("Error!");
        }

        Console.ReadLine();
    }

    public static dynamic GetDynamicObject()
    {
        return new MyDynamicObject();
    }
}


public class MyDynamicObject : DynamicObject
{
    public static implicit operator int(MyDynamicObject obj)
    {
        return 0;
    }

    public static implicit operator long(MyDynamicObject obj)
    {
        return 0;
    }

    public static implicit operator double(MyDynamicObject obj)
    {
        return 0;
    }

    // Works when commented
    public static implicit operator string(MyDynamicObject obj)
    {
        return null;
    }

    public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
    {
        Console.WriteLine("MyDynamicObject.TryBinaryOperation");
        return base.TryBinaryOperation(binder, arg, out result);
    }  
}

例外情况:

代码语言:javascript
复制
Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException was unhandled
  HResult=-2146233088
  Message=An unexpected exception occurred while binding a dynamic operation
  Source=Microsoft.CSharp
  StackTrace:
       at Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder.WhichSimpleConversionIsBetter(PredefinedType pt1, PredefinedType pt2)
       at Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder.WhichTypeIsBetter(PredefinedType pt1, PredefinedType pt2, CType typeGiven)
       at Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder.WhichBofsIsBetter(BinOpFullSig bofs1, BinOpFullSig bofs2, CType type1, CType type2)
       at Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder.FindBestSignatureInList(List`1 binopSignatures, BinOpArgInfo info)
       at Microsoft.CSharp.RuntimeBinder.Semantics.ExpressionBinder.BindStandardBinop(ExpressionKind ek, EXPR arg1, EXPR arg2)
       at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindBinaryOperation(CSharpBinaryOperationBinder payload, ArgumentObject[] arguments, Dictionary`2 dictionary)
       at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.DispatchPayload(DynamicMetaObjectBinder payload, ArgumentObject[] arguments, Dictionary`2 dictionary)
       at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.BindCore(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, DynamicMetaObject& deferredBinding)
       at Microsoft.CSharp.RuntimeBinder.RuntimeBinder.Bind(DynamicMetaObjectBinder payload, IEnumerable`1 parameters, DynamicMetaObject[] args, 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.DynamicObject.MetaDynamic.<>c__DisplayClass9_0.<BindBinaryOperation>b__0(DynamicMetaObject e)
       at System.Dynamic.DynamicObject.MetaDynamic.CallMethodWithResult(String methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke)
       at System.Dynamic.DynamicObject.MetaDynamic.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[T](CallSite`1 site, Object[] args)
       at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
       at WIG.Common.Tests.Program.Main(String[] args) in C:\WIG\WIG Framework\Dev\WIG.Common.Tests\Program.cs:line 74
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-19 00:39:23

这是框架中的一个bug (编辑:固定在corefx代码基中,所以.NET Core2.0.4和更高版本不应该看到这个问题)。我们可以看到,在没有dynmic的情况下,DynamicObject也会发生同样的情况。

代码语言:javascript
复制
public class Castable
{
    public static implicit operator int(Castable obj) => 3;

    public static implicit operator string(Castable obj) => "abc";
}

…

dynamic d = new Castable();
var result = d + 2;    // Throws RuntimeBinderInternalCompilerException in NetFX
                       // IndexOutOfRangeException in CoreFX.

dynamic更改为var,静态绑定器正在工作,而不是动态的,并且(没有此bug)将result设置为5。注释掉转换操作符和动态绑定器可以使用另一个罚款。

问题是,如何处理与+一起使用的转换(作为内置操作符用于加法和字符串连接)的处理,会遇到一个不匹配的错误。

如您所知,1 + 2被视为一个加法,而"abc" + x则被视为string.Concat("abc", x)。在d + 1的情况下,ddynamic,活页夹需要找出使用哪一个。

在比较可能性时,会在表中查找一些“简单”目标类型。如果这是可能的,那么目标的枚举值将低于给定的值,所以很明显,首先要做的就是看看是否是这样的。

但是不幸的是,该检查使用了<=,而不是<,但是与之相比,这个限制比最高允许的多一个,所以<是正确的。刚好超过这个极限的值是string。因此,如果您将动态绑定放在它选择转换为“简单”类型和转换为字符串之间的情况下,它决定可以将这两种可能性进行比较,因为这两种可能性都是“简单的”,尝试在查找表中找到答案,索引超出数组的范围。根据版本的不同,它会使用IndexOutOfRangeException,或者点击一个断言,以确保它没有精确地完成它将要做的事情,并且使用了RuntimeBinderInternalCompilerException

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34709413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档