Is there a way to test if a variable is dynamic?
Asked Answered
G

5

24

The following piece of code will always return true unless the variable v is null:

v is dynamic

and the following test will not compile ("The typeof operator cannot be used on the dynamic type"):

v.GetType() == typeof(dynamic)

So is there a way to test if the variable is dynamic?

Germinative answered 5/11, 2013 at 9:33 Comment(7)
For those people with a longer Microsoft experience, dynamic is the new IDispatch. Think really hard whether you want to deal with it.Kauslick
Related: how-do-i-test-for-typeofdynamic?rq=1Inchoation
@Inchoation Interesting problem! It's a shame methods don't readily exist for that kind of problem - maybe something that will be in the next version of the DRL.Germinative
@Germinative what is the kind of dynamic you're trying to detect? Can you show us an example how variable v is declared and used? Or go thru the comment section of my answer, you might get better idea..Inchoation
@Inchoation Actually the problem I was having was the one you linked to but my question was more general. As Marc said in your comment chain - sometimes the OP (me) doesn't know what they're asking. Still - I feel changing question after so many people have answered is against the SO way.Germinative
@Germinative you need not change the question as such. You can add more details. Or ask another sub question related to the first one. Use the edit feature. It is encouraged on SO. I say this because without context, we do not know what dynamic is. If you already understood the concept, then that's fine. But it may help future visitors.Inchoation
possible duplicate of Reflect on a dynamic type to tell if it was a dynamic type, to begin withInchoation
E
19

Firstly, you need to separate the variable and the object. A variable is dynamic if it is defined as dynamic. That is all. There is nothing more. A field or property would be annotated with the [Dynamic] attribute, i.e.

public dynamic Foo {get;set;}

is actually:

[Dynamic]
public object Foo {get;set;}

This basically acts as a prompt for the compiler to access the object via the dynamic API rather than via the OOP API.

An object supports full dynamic capabilities if it implements IDynamicMetaObjectProvider - however, such an object can be accessed via both the dynamic API and via the regular OOP API (it can have both). Equally, an object that doesn't implement IDynamicMetaObjectProvider can be accessed via either API (but: only the public members will be available via dynamic).

Ellswerth answered 5/11, 2013 at 9:38 Comment(0)
S
14

There is no CLR type called dynamic. The C# compiler makes all dynamic values of type object and then calls custom binding code to figure out how to handle them. If dynamic was used, it will show up as Object.

But You can check if an instance is of type IDynamicMetaObjectProvider or you can check whether the type implements IDynamicMetaObjectProvider

Subaltern answered 5/11, 2013 at 9:36 Comment(3)
An instance is never "of type IDynamicMetaObjectProvider", since that is not a concrete type. The type can implement that, of course (the second half of that sentence is fine).Ellswerth
@MarcGravell, from polymorphism's point of view class Foo implementing IFoo IS-A IFoo. Probably my English is not perfect.Subaltern
Here is an example: typeof(IDynamicMetaObjectProvider).IsAssignableFrom(typeof(ExpandoObject))Bradfield
F
2

In C# dynamic means no complile-time check and it's gonna have the type of the other side of the = symbol. However GetType is a runtime evaluation, so you always gonna retrieve declared type and not dynamic.

You can read a little bit more here: http://msdn.microsoft.com/en-us/magazine/gg598922.aspx

Fraternity answered 5/11, 2013 at 9:40 Comment(0)
I
0

There will always be a run-time type as others have said.

There is a hack to detect for local variables, relying on the fact that dynamic variables doesn't support extension methods.

static void DummyDynamicTest<T>(this T t) //extension method
{

}

dynamic test = 1;
try
{
    test.DummyDynamicTest();
    //not dynamic
}
catch (RuntimeBinderException)
{
    //dynamic
}

However you can't refactor the functionality into another method. This can't be very useful at all in any meaningful scenarios, ignore at any cost.

Inchoation answered 5/11, 2013 at 10:9 Comment(12)
Surely checking for test is IDynamicMetaObjectProvider is simpler, more efficient, and more correct?Ellswerth
@nawful what case is that? concrete example? (genuinely interested)Ellswerth
@MarcGravell the same. dynamic test = 1;. Now test is IDynamicMetaObjectProvider; returns false.Inchoation
ah, I see - we're talking at cross purposes: you're talking purely about the variable; I was talking about the value. When it comes to the variable, that is defined 100% by the variable declaration - I'm not sure how useful it actually is to "test" the defined type of a local variable, since that is right there in the definition. The simpler "test" there is : look at the definition. It is a bit like asking whether string x; is an int... well, no - it is a string. You don't need a test for that.Ellswerth
@MarcGravell OP is after variable declaration. I agree it is not at all useful in the context I have used. What do you mean by value being dynamic? I did not get that part. In other words, in which case does IDynamicMetaObjectProvider comes handy? (genuinely interested)Inchoation
it is pretty common that what the OP asks for is not exactly the correct words for what they mean. Especially with things like "variables" vs "values" vs "references", etc. Re the interface: that is the interface that the dynamic implementation uses to decide whether to look for reflection methods (i.e. a method called DummyDynamicTest, accessed normally) vs the full dynamic invoke route (a dynamic object can run methods that don't exist). In fact, it is really easy too - marcgravell.blogspot.co.uk/2013/04/…Ellswerth
The try ... catch... expression is never a correct way of checking stuff.Subaltern
@KrzysztofCieslak oh, I don't know... "can I actually talk to the database on this connection that claims to be open" is something where I suspect try/catch might be the only route. But I agree it seems undesirable here.Ellswerth
@MarcGravell, In such case is it really check if database is up or it is handling unexpected behaviour - database is not up ?Subaltern
@KrzysztofCieslak that depends a bit on your definition of "expected" / "unexpected" ;p but yes, I think we're somewhere near the same page hereEllswerth
@MarcGravell ah, I understand you. So that means for something like dynamic test = new ExpandoObject();, test is IDynamicMetaObjectProvider; returns true. But I don't think OP's after such truly dynamic objects. Most probably he is after dynamic declarations in which case there is no reliable way.Inchoation
@KrzysztofCieslak of course not, and it is written all over my answer. It wasn't a serious solution to OP's problem, but an answer that shows one aspect of dynamic which can be handled. Not sure who downvoted.Inchoation
Z
-1

@nawfal Sadly your extension method fails when any normal poco class that is not dynamic is passed in.

@Marc Gravell's proposed solution is correct. I think the confusion lies around the fact that even though you can declare anything as dynamic. However, when you instantiate it to a concrete class then it is no longer truly dynamic. Here are some tests I threw at it. Only test2 and test3 should pass. You can further test it out by trying to set some property that does not exist on each dynamic. Which will cause an exception on the non dynamic dynamics. :)

class Program
{
    private class MyDynamic: DynamicObject
    {

    }

    static void Main(string[] args)
    {
        dynamic test1 = new { Name = "Tim" };
        //although I used the dynamic keyword here, it is NOT dynamic. dynamics are only dynamics if they support dynamically adding properties
        //uncommenting this line will cause an exception
        //test.LastName = "Jones"
        if (test1 is IDynamicMetaObjectProvider) { Console.WriteLine("test1"); }

        dynamic test2 = new MyDynamic();
        if (test2 is IDynamicMetaObjectProvider) { Console.WriteLine("test2"); }

        dynamic test3 = new ExpandoObject();
        if (test3 is IDynamicMetaObjectProvider) { Console.WriteLine("test3"); }

        dynamic test4 = new List<string>();
        if (test4 is IDynamicMetaObjectProvider) { Console.WriteLine("test4"); }
    }
}
Ziagos answered 28/4, 2016 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.