Search code examples
dynamicc#-4.0duck-typing

Duck type testing with C# 4 for dynamic objects


I'm wanting to have a simple duck typing example in C# using dynamic objects. It would seem to me, that a dynamic object should have HasValue/HasProperty/HasMethod methods with a single string parameter for the name of the value, property, or method you are looking for before trying to run against it. I'm trying to avoid try/catch blocks, and deeper reflection if possible. It just seems to be a common practice for duck typing in dynamic languages (JS, Ruby, Python etc.) that is to test for a property/method before trying to use it, then falling back to a default, or throwing a controlled exception. The example below is basically what I want to accomplish.

If the methods described above don't exist, does anyone have premade extension methods for dynamic that will do this?


Example: In JavaScript I can test for a method on an object fairly easily.

//JavaScript
function quack(duck) {
  if (duck && typeof duck.quack === "function") {
    return duck.quack();
  }
  return null; //nothing to return, not a duck
}


How would I do the same in C#?

//C# 4
dynamic Quack(dynamic duck)
{
  //how do I test that the duck is not null, 
  //and has a quack method?

  //if it doesn't quack, return null
}

Solution

  • Try this:

        using System.Linq;
        using System.Reflection;
        //...
        public dynamic Quack(dynamic duck, int i)
        {
            Object obj = duck as Object;
    
            if (duck != null)
            {
                //check if object has method Quack()
                MethodInfo method = obj.GetType().GetMethods().
                                FirstOrDefault(x => x.Name == "Quack");
    
                //if yes
                if (method != null)
                {
    
                    //invoke and return value
                    return method.Invoke((object)duck, null);
                }
            }
    
            return null;
        }
    

    Or this (uses only dynamic):

        public static dynamic Quack(dynamic duck)
        {
            try
            {
                //invoke and return value
                return duck.Quack();
            }
            //thrown if method call failed
            catch (RuntimeBinderException)
            {
                return null;
            }        
        }