Tips for Working with the dynamic Type in C#
By Harry Bellamy
- 2 minutes read - 402 wordsThe dynamic type was introduced in C# 4 to avoid static type checking. This allows working with data without a predefined schema.
Any type can be assigned to the dynamic type. Any method calls will be checked at runtime - this means that attempting to call a method or access a property that doesn’t exist will result in a runtime exception rather than being detected at compile time.
Checking for the Existence of Properties
Any type can be assigned to a dynamic variable, but for a ‘true’ dynamic type (i.e. one that can have additional properties added at runtime) it will be an ExpandoObject
.
Under the hood, ExpandoObject
implements IDictionary<string, object>
- this is basically a mapping from property name to object value.
Therefore we can check for the existence of properties like so:
public static bool HasProperty(dynamic item, string propertyName)
=> (item as IDictionary<string, object>).ContainsKey();
For ‘standard’ .Net types, you can use a reflection-based approach to checking for the existence of properties:
public static bool HasProperty(dynamic item, string propertyName)
=> test1.GetType().GetProperty(propertyName);
For completeness (and avoid runtime errors), we could combine these two functions like so:
public bool HasProperty(dynamic item, string propertyName)
{
if (item is ExpandoObject eo)
{
return (eo as IDictionary<string, object>).ContainsKey(propertyName);
}
else
{
return item.GetType().GetProperty(propertyName);
}
}
Working with Enumerables and LINQ
When using the source of a dynamic type, it is good practice to encapsulate the usage of the dynamic type to just the class that calls it directly. Doing this means we don’t have to keep checking for the existence of properties on the dynamic object and allows for testing against more robust definitions.
Consider the follow code that attempts to convert from IEnumerable<dynamic>
to IEnumerable<string>
(it could be any T
).
using System.Collections.Generic;
using System.Linq;
// This code does NOT compile.
private static IEnumerable<string> GetData()
{
IEnumerable<dynamic> records = someService.GetRecords();
return records
.Where(w => w.Field1 != string.Empty)
.Select(s => s.Field1.ToString())
.ToList();
}
This code looks like it should be fine, right?
Unfortunately it doesn’t compile. Despite the explicit ToString()
inside the Select()
it still returns an IEnumerable<dynamic>
.
To get round this we have to use Enumerable.Cast<T>
, which converts it to a static type.
using System.Collections.Generic;
using System.Linq;
private static IEnumerable<string> GetData()
{
IEnumerable<dynamic> records = someService.GetRecords();
return records
.Where(w => w.Field1 != string.Empty)
.Select(s => s.Field1.ToString())
.Cast<string>()
.ToList();
}
Further Information
For more information and examples of the dynamic type, start by looking at Microsoft’s documentation.