dynamic это тот же object, просто игнорирует все проверки на тип во время компиляции. Соответственно, вы можете попытаться вызывать у него любые методы и среда вам даст скомпилировать такую программу. Далее методы вызываются по сигнатуре (имя + типы аргументов). Если у динамического объекта вызвать метод с сигнатурой, отсутствующей в реальном объекте, который упакован в этом динамике, то выпадет исключение рантайма.
Простой пример.
class First{
public First(){}
public void test(string str){}
}
class Second{
public Second(){}
public void test(string str, int i){}
}
static void Main()
{
dynamic myObj=new First();
myObj.test("some string");//ok
myObj=new Second();
myObj.test("some string");// runtime error, требуется сигнатура test(string,int). То же самое будет если вызвать не существующий метод
}
Ответ на ваш вопрос: попытавшись то же самое сделать с object вы не сможете скомпилировать данную программу, вам нужно будет пользоваться приведением типов.
Более того, если модифицировать пример так, чтобы методы test в разных классах имели одинаковую сигнатуру, то dynamic отработает вызов метода в любом случае. А приведение типа потребуется в каждом случае в свой класс, иначе возникнет ошибка.
class First{
public First(){}
public void test(string str){}
}
class Second{
public Second(){}
public void test(string str){}
}
static void Main()
{
object myObj=new First();
(myObj as First).test("some string");//ok
//myObj.test("some string"); такое не даст скомпилироваться
myObj=new Second();
(myObj as First).test("some string");// runtime error, требуется тип Second хотя сигнатура метода та же самая
}