'Is the use of dynamic considered a bad practice?

In C#, someone can do:

MyClass myInstance        = new MyClass();
dynamic mydynamicInstance = myInstance;

And then, invoke a method, like:

//This method takes a MyClass argument and does something.
Caller.InvokeMethod(myDynamicInstance);

Now, this will lead to determination of the myInstance type at runtime, and, if it is valid, the Caller.InvokeMethod will be called normally.

Now, my question is if this is considered a bad practice to use dynamic, especially in the following cases:

1) InvokeMethod instantiates another instance of myDynamicInstance type, using reflection inside.

2) There is an abstract base class MyBaseClass and a number of subclasses of it, including MyBaseClass. If we have a number of overloaded methods of InvokeMethod for all of those derived classes, could we use it in order to allow at runtime the type determination and then the proper invocation via method overloading (or late binding on the call of a method of that class)?:

public abstract class MyBaseClass         {/*...*/}
public class MyClass        : MyBaseClass {/*...*/}
public class MyAnotherClass : MyBaseClass {/*...*/}

MyBaseClass myBaseClassRef = new MyClass();
dynamic myDynamicInstance  = myBaseClassRef;

Caller.InvokeMethod(myDynamicInstance);


Solution 1:[1]

I don“t fully agree with Fabien that it does not give you additional benefits. What he is solving with the visitor pattern is called Multiple dispatch and dynamic can provide a clean solution to this too. Sure you have to know the implications Fabien mentioned like performance, static type checking...

public abstract class MyBaseClass
{
}

public class MyClass : MyBaseClass
{
}
public class MyAnotherClass : MyBaseClass
{
}

public class ClassThatIsUsingBaseClass
{
    public static void PrintName(MyBaseClass baseClass)
    {
        Console.WriteLine("MyBaseClass");
    }

    public static void PrintName(MyClass baseClass)
    {
        Console.WriteLine("MyClass");
    }

    public static void PrintName(MyAnotherClass baseClass)
    {
        Console.WriteLine("MyAnotherClass");
    }

    public static void PrintNameMultiDispatch(MyBaseClass baseClass)
    {
        ClassThatIsUsingBaseClass.PrintName((dynamic)baseClass);
    }
}

And usage is

static void Main(string[] args)
{
    MyBaseClass myClass = new MyClass();
    MyBaseClass myAnotherClass = new MyAnotherClass();
    ClassThatIsUsingBaseClass.PrintName(myClass);
    ClassThatIsUsingBaseClass.PrintName(myAnotherClass);
    ClassThatIsUsingBaseClass.PrintNameMultiDispatch(myClass);
    ClassThatIsUsingBaseClass.PrintNameMultiDispatch(myAnotherClass);

    Console.ReadLine();
}

Output is

MyBaseClass
MyBaseClass
MyClass
MyAnotherClass

Search for "Multiple dispatch" and "C# multiple dispatch" for more infos.

Solution 2:[2]

This was answered in 2015, today in 2019 with the patterns we see in JavaScript and Typescript indeed there are good reasons for using dynamic; however, it requires the developer to take caution.

    private (Boolean Valid, dynamic Result) ValidatePersonID(int ID)
    {
        var person = _store.Persons.FirstOrDefault(person => person.ID == ID);
        if (person == null)
        {
            string message = $"The person id {ID} does not exist, please try again.";
            return (false, message);
        }
        return (true, person);

    }

To use the code above:

   var operation = ValidatePersonID(personID);
   if (operation.Valid == false)
     {
        //BadRequest takes a string and C# uses co-variance to make it work.
        return BadRequest(operation.Result);
     }
   //otherwise just cast the type, but requires the cast to always work.
   var pe = (Person)operation.Result;
   ...

The return of validity being either True, or False determines the type being returned. We still pick up strong typing using the cast and or the required input type on BadRequest. We also pick up compile time type checking in that if one of the two returned types ever changes to something other than string, and or person, it won't compile.

I consider this a form of Dependency Injection whereby we achieve different behaviors depending on what we inject. C# purists don't like this idea but Typescript people do it all the time.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Muraad Nofal
Solution 2