February 14, 2022
I’m writing on C# for 5 years now and keep finding things, that are not widely used, but they are exist already for a long time. Just recently I found the need of dynamic
keyword.
Usually new variables are defined with var
or with value type directly:
Foo foo = new Foo(); var foo = new Foo();
These are actually two identical lines, compiler would define actual type on second lane from right-hand operator.
But what if type is unknown in compile type? I have met a problem, where actual type is created by external parameter - and there is no common interface that can be used to aggregate possible types. In these uncommon scenarios dynamic
can be very handy.
Suppose, we have a three types:
public record TypeA(string A); public record TypeB(string B); public record TypeC(string C);
Then we can declare a function, which return any of this types by random:
dynamic GetRandomType(Random random) => random.Next(3) switch { 0 => new TypeA("a"), 1 => new TypeB("b"), 2 => new TypeC("c"), _ => throw new Exception("out of random range") };
By making dynamic
return type, we tell a compiler, that he should not care, which type it actually is. Problem here in that compiler agreed and skip any further compile-time checking:
var random = new Random(); var result = GetRandomType(random); result.DoSomething(); // We would get runtime error here
A good thing is, that actual type is available in run time and overloading works even with dynamic type:
public class Foo { public static void Do(TypeA obj) => Console.WriteLine($"Do a: {obj.A}"); public static void Do(TypeB obj) => Console.WriteLine($"Do b: {obj.B}"); public static void Do(TypeC obj) => Console.WriteLine($"Do c: {obj.C}"); }
Foo.Do(result); // correct function would be called, based on result type
This can be very handful for places, where actual behaviour is unknown beforehand. As example, I wrote a event parser, where each event contain a enum with event type and object
payload. And for each actual event the payload would be a completely different DTO, as well as event handlers would have completely different behaviour.