C# DLR, Datatype inference with Dynamic keyword

后端 未结 2 480
暖寄归人
暖寄归人 2021-02-10 03:38

Just Asking :

Why \'withOffset\' variable is inferred as dynamic as Parse method returns Struct ?

dynamic str         


        
2条回答
  •  北海茫月
    2021-02-10 04:10

    Here's a really good example of where your assumptions about return type begin to go awry.

    public class Bar
    {
        public string Foo(string value)
        {
            return value;
        }
    }
    

    As you can see here, Bar clearly has an instance method Foo that takes a string and returns a string.

    public class Baz : Bar, IDynamicMetaObjectProvider
    {
        public DynamicMetaObject GetMetaObject(Expression parameter)
        {
            return new BazMetaObject(parameter, this);
        }
    }
    

    But now I've created a derived class that also implements IDynamicMetaObjectProvider. This is the interface that C# uses to get a DynamicMetaObject, which determines how the dynamic calls are bound at runtime. For example:

    public class BazMetaObject : DynamicMetaObject
    {
        public BazMetaObject(Expression expression, Baz value)
            : base(expression, BindingRestrictions.Empty, value)
        {
        }
    
        public override DynamicMetaObject BindInvokeMember(
            InvokeMemberBinder binder, DynamicMetaObject[] args)
        {
            if (binder.Name == "Foo")
            {
                return new DynamicMetaObject(
                    Expression.Convert(
                        Expression.Call(
                            typeof (BazMetaObject).GetMethod("DynamicFoo")
                        ),
                        typeof (object)
                    ),
                    BindingRestrictions.GetTypeRestriction(
                        this.Expression,
                        this.LimitType
                    )
                );
            }
    
            return base.BindInvokeMember(binder, args);
        }
    
        public static int DynamicFoo()
        {
            return 1234;
        }
    }
    

    This DynamicMetaObject overload will capture any calls to Foo and dynamically redirect them to DynamicFoo, which has a completely different signature—including that it returns int, not string.

    So, if you were to do this...

    dynamic value = "Hello, world!";
    
    Bar bar = new Baz();
    var returnValue = bar.Foo(value);
    

    ...the value of returnValue at runtime would be 1234, not "Hello, world!".

    Now, in the real world, this is insanely evil. While it's possible to completely rebind functions that are expected to do something in a certain way, doing something ridiculous like this will only serve to confuse people down the road. That being said, it is completely possible in the CLR.

    TL;DR: When you're using dynamic, you can't always be certain of things you think are correct.

提交回复
热议问题