How does the "is" operator work with dynamic objects?
Asked Answered
A

2

9

How does the is operator work with respect to the DLR?

To make my question a little more explicit, consider the following signature:

 public bool Is<T>(Func<dynamic> getInstance)
 { 
     return getInstance() is T;
 }

By default, what conditions are necessary for Is<T> to return true? Furthermore, does the DLR provide any mechanism to customize this behavior?

Agnola answered 28/3, 2013 at 17:53 Comment(12)
What type of customization behavior would you want?Henden
@ReedCopsey, granular ducktyping: I would like to be able to do something like have an interface: public interface INamed { string Name { get; } } and when I check getInstance() is INamed to have my custom DynamicMetaObject implementation return true iff the dynamic object contains a string property named "Name". Any suggestions?Agnola
You'd need to implement the checks yourself, probably by using reflection against the interface, etc.Henden
a is B <=> typeof(B).IsAssignableFrom(a.GetType())Ropy
@ReedCopsey, I get that. But is there any way to map the is syntax to those checks?Agnola
@dialer, except for when a == nullAgnola
@Agnola structural typing with DynamicMetaObject, is pretty much impossible as it doesn't have an api for testing for implementation. I wrote a full library that provides easy access to pretty much all c# dlr apis.Booze
@jbtule, maybe... I'm thinking that I could get what I want by generating dynamic proxies that implement all these interfaces and inherit from the assigned T type. Do you see a problem here?Agnola
@Agnola Well that's where framework started, IMyInterface myInterface = Impromptu.ActLike(expando). Dynamic Implementation static interface.Booze
@jbtule, I've actually read over the source of impromptu before, but haven't used it. Does it support what I'm describing out of the box?Agnola
@Agnola It won't test for an interface on an IDynamicMetaObjectProvider, but you can wrap a static interface around any IDynamicMetaObjectProvider and that interface can be tested for.Booze
let us continue this discussion in chatBooze
H
6

At runtime, dynamic is treated the same as object, which means that the runtime type of the getInstance delegate's result will be used to perform this check. The only difference using dynamic here will cause is that there will be no compile time checking, and dynamic binding will be used at runtime to perform this check on the dynamic object returned by getInstance.

By default, what conditions are necessary for Is to return true?

The delegate passed in will need to return a type which, at runtime, is compatible with T.

Furthermore, does the DLR provide any mechanism to customize this behavior?

No. This is going to use the standard rules for C# types. Any custom behavior would need to be written into the logic itself.

Henden answered 28/3, 2013 at 17:54 Comment(3)
So, the result is the same as typeof(T).GetType().IsInstanceOfType(getInstance())?Agnola
@Agnola It's more like using Type.IsAssignableFrom, ie: typeof(T).IsAssignableFrom(getInstance().GetType())Henden
There aren't actually any differences in this case to using object.Booze
B
0

Since is already is a runtime test, there is no extra runtime binding being done, in fact there won't be any compiled IL difference to

 public bool Is<T>(Func<object> getInstance)
 { 
     return getInstance() is T;
 }

The IL for the method body of both Is<T>(Func<object> getInstance) and Is<T>(Func<dynamic> getInstance):

    .maxstack 2
    .locals init (
        [0] bool CS$1$0000)
    L_0000: nop 
    L_0001: ldarg.1 
    L_0002: callvirt instance !0 [mscorlib]System.Func`1<object>::Invoke()
    L_0007: isinst !!T
    L_000c: ldnull 
    L_000d: cgt.un 
    L_000f: stloc.0 
    L_0010: br.s L_0012
    L_0012: ldloc.0 
    L_0013: ret 

So the answer is that is keyword is not effected by the usage of the DLR, it works the same as if you use the type object.

Booze answered 28/3, 2013 at 18:3 Comment(4)
So there is no compiled difference at all? What if it was an instance of DynamicObject or something like that?Fosque
If it's a DynamicObject it will only be true if bool Is<DynamicObject>. And yes you can write the code, compile it and both ways will be the same IL in this case.Booze
I'm not so sure about that. DynamicObject is treated specially. It can be used to customize lots of behavior (think of ExpandoObject). It also has a TryConvert function. Also, what if the object is a python object? I'm sure python rules for type conversion are different so they are probably customizable?!Fosque
@Fosque is doesn't trigger type conversion in c#. If the runtime could change is behavior any more then the compiler would generate dynamic binding code, but it doesn't. I've added the IL to the answer.Booze

© 2022 - 2024 — McMap. All rights reserved.