C# DLR, Datatype inference with Dynamic keyword

后端 未结 2 481
暖寄归人
暖寄归人 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:01

    When you use dynamic, the entire expression is treated at compile time as a dynamic expression, which causes the compiler to treat everything as dynamic and get run-time binding.

    This is explained in 7.2 of the C# Language specification:

    When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of constituent expressions are used in the selection process. However, when one of the constituent expressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.

    This basically means that most operations (the types are listed in section 7.2 of the spec) which have any element that is declared as dynamic will be evaluated as dynamic, and the result will be a dynamic.


    this is because in below line str is dynamic

             dynamic str = "22/11/2013 10:31:45 +00:01";
            var withOffset = DateTimeOffset.Parse(str);
    

    At compile time str is dynamic, the type of str get to know at runtime only that is the reason compiler treat withOffset as dynamic


    its known to you that str is get converted to datetime structure but for compiler that it get to know only at runtime...

    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题