An efficient .NET object inspector/accesor to avoid reflection usage.
PropertyFetcher, FieldFetcher, MethodCaller and DuckTyping for .NET by Expression Trees or Emitting IL at runtime.
netstandard2.0, netstandard2.1, netcoreapp2.0, netcoreapp2.1, net461, net462, net471, net472, net48 and net45.
System.Reflection.Emit (>= 4.7.0)System.Reflection.Emit.Lightweight (>= 4.7.0)
Given the following class with private members, the object inspector can help you to Get, Set or Invoke members of the object instance:
namespace OtherAssembly
{
public class SomeClass
{
private string _privateField = "This field it's so private...";
private string PrivateProperty { get; set; } = "You can't read this";
private void PrivateConsoleWrite(string line) => Console.WriteLine(line);
}
public static class ObjectFactory
{
public static object New() => new SomeClass();
}
}Note You can inspect, public or non public types with public or non public members, also it's compatible with anonymous objects. As you can see in the following code:
Duck Typing can be done by using an Interface, Abstract class or a class with virtual members. The library will create a proxy type inheriting/implementing the base type.
namespace MyAssembly
{
public interface IDuckSomeClass
{
[Duck(Name="_privateField", Kind = DuckKind.Field, Flags = DuckAttribute.AllFlags)]
string PrivateField { get; set; }
[Duck(Flags = DuckAttribute.AllFlags)]
string PrivateProperty { get; set; }
[Duck(Flags = DuckAttribute.AllFlags)]
void PrivateConsoleWrite(string line);
}
public class Program
{
public static void Main()
{
var obj = OtherAssembly.ObjectFactory.New();
HandleObject(obj);
}
public static void HandleObject(object obj)
{
// We can treat the object as it were implementing the IDuckSomeClass interface
var duck = obj.DuckAs<IDuckSomeClass>();
Console.WriteLine(duck.PrivateField);
Console.WriteLine(duck.PrivateProperty);
Console.WriteLine();
duck.PrivateField += " or not!";
duck.PrivateProperty += ". I think I can!";
Console.WriteLine(duck.PrivateField);
Console.WriteLine(duck.PrivateProperty);
Console.WriteLine();
duck.PrivateConsoleWrite("Sooo private...");
}
}
}namespace MyAssembly
{
public class Program
{
public static void Main()
{
var obj = OtherAssembly.ObjectFactory.New();
HandleObject(obj);
}
private static readonly DynamicFetcher _privateFieldFetcher = new DynamicFetcher("_privateField", DuckAttribute.AllFlags);
private static readonly DynamicFetcher _privatePropertyFetcher = new DynamicFetcher("PrivateProperty", DuckAttribute.AllFlags);
private static readonly DynamicFetcher _privateConsoleWriteFetcher = new DynamicFetcher("PrivateConsoleWrite", DuckAttribute.AllFlags);
public static void HandleObject(object obj)
{
// We can handle the object using a dynamic fetcher
Console.WriteLine((string)_privateFieldFetcher.Fetch(obj));
Console.WriteLine((string)_privatePropertyFetcher.Fetch(obj));
Console.WriteLine();
_privateFieldFetcher.Shove(obj, "This field it's so private... or not!");
_privatePropertyFetcher.Shove(obj, "You can't read this. I think I can!");
Console.WriteLine((string)_privateFieldFetcher.Fetch(obj));
Console.WriteLine((string)_privatePropertyFetcher.Fetch(obj));
Console.WriteLine();
_privateConsoleWriteFetcher.Invoke(obj, "Sooo private...");
}
}
}namespace MyAssembly
{
public class Program
{
public static void Main()
{
var obj = OtherAssembly.ObjectFactory.New();
HandleObject(obj);
}
public static void HandleObject(object obj)
{
var inspector = new ObjectInspector(new InspectName("_privateField", DuckAttribute.AllFlags),
new InspectName("PrivateProperty", DuckAttribute.AllFlags),
new InspectName("PrivateConsoleWrite", DuckAttribute.AllFlags));
var viewer = inspector.With(obj);
Console.WriteLine((string)viewer["_privateField"]);
Console.WriteLine((string)viewer["PrivateProperty"]);
Console.WriteLine();
viewer["_privateField"] = "This field it's so private... or not!";
viewer["PrivateProperty"] = "You can't read this. I think I can!";
Console.WriteLine((string)viewer["_privateField"]);
Console.WriteLine((string)viewer["PrivateProperty"]);
Console.WriteLine();
viewer.Invoke("PrivateConsoleWrite", "Sooo private...");
}
}
}namespace MyAssembly
{
public class Program
{
public static void Main()
{
var obj = OtherAssembly.ObjectFactory.New();
HandleObject(obj);
}
public static void HandleObject(object obj)
{
var inspTuple = new InspectorTuple<string, string, object>(new InspectName("_privateField", DuckAttribute.AllFlags),
new InspectName("PrivateProperty", DuckAttribute.AllFlags),
new InspectName("PrivateConsoleWrite", DuckAttribute.AllFlags));
inspTuple.SetInstance(obj);
Console.WriteLine(inspTuple.Item1);
Console.WriteLine(inspTuple.Item2);
Console.WriteLine();
inspTuple.Item1 = "This field it's so private... or not!";
inspTuple.Item2 = "You can't read this. I think I can!";
Console.WriteLine(inspTuple.Item1);
Console.WriteLine(inspTuple.Item2);
Console.WriteLine();
inspTuple.InvokeItem3("Sooo private...");
}
}
}BenchmarkDotNet=v0.12.1, OS=ubuntu 19.10
AMD Ryzen Threadripper 2950X, 1 CPU, 32 logical and 16 physical cores
.NET Core SDK=3.1.101
[Host] : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT
DefaultJob : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0057 ns | 0.0032 ns | 0.0030 ns | 0.0000 ns | 0.0088 ns | 0.004 | 0.00 | - | - | - | - |
| DuckTypeInterface | 2.1733 ns | 0.0088 ns | 0.0082 ns | 2.1614 ns | 2.1859 ns | 1.498 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 1.4507 ns | 0.0058 ns | 0.0055 ns | 1.4409 ns | 1.4586 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 1.4454 ns | 0.0027 ns | 0.0026 ns | 1.4419 ns | 1.4499 ns | 0.996 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.3870 ns | 0.0163 ns | 0.0136 ns | 4.3561 ns | 4.4048 ns | 3.024 | 0.01 | - | - | - | - |
| EmitFetcher | 4.4331 ns | 0.0154 ns | 0.0144 ns | 4.4125 ns | 4.4654 ns | 3.056 | 0.01 | - | - | - | - |
| DelegateFetcher | 6.4340 ns | 0.0188 ns | 0.0176 ns | 6.3985 ns | 6.4617 ns | 4.435 | 0.02 | - | - | - | - |
| Reflection | 107.0668 ns | 0.2081 ns | 0.1845 ns | 106.6127 ns | 107.2895 ns | 73.802 | 0.32 | - | - | - | - |
| Method | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.000 | 0.00 | - | - | - | - |
| DuckTypeInterface | 1.6644 ns | 0.0080 ns | 0.0075 ns | 1.6657 ns | 1.6513 ns | 1.6773 ns | 1.193 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 1.3947 ns | 0.0074 ns | 0.0069 ns | 1.3967 ns | 1.3803 ns | 1.4034 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 1.4578 ns | 0.0124 ns | 0.0116 ns | 1.4568 ns | 1.4429 ns | 1.4750 ns | 1.045 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 12.2679 ns | 0.2723 ns | 0.5438 ns | 12.5072 ns | 10.9949 ns | 12.9669 ns | 8.489 | 0.45 | 0.0014 | - | - | 24 B |
| EmitFetcher | 12.0793 ns | 0.2696 ns | 0.2648 ns | 12.1251 ns | 11.6069 ns | 12.6324 ns | 8.654 | 0.21 | 0.0014 | - | - | 24 B |
| DelegateFetcher | 15.7135 ns | 0.1862 ns | 0.1742 ns | 15.8033 ns | 15.3563 ns | 15.8849 ns | 11.267 | 0.16 | 0.0014 | - | - | 24 B |
| Reflection | 165.7264 ns | 0.7783 ns | 0.7280 ns | 165.4518 ns | 164.8954 ns | 167.2588 ns | 118.828 | 0.89 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 1.433 ns | 0.0095 ns | 0.0079 ns | 1.421 ns | 1.446 ns | 0.60 | 0.00 | - | - | - | - |
| DuckTypeInterface | 2.870 ns | 0.0080 ns | 0.0071 ns | 2.856 ns | 2.885 ns | 1.21 | 0.00 | - | - | - | - |
| DuckTypeAbstract | 2.371 ns | 0.0063 ns | 0.0049 ns | 2.357 ns | 2.377 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.366 ns | 0.0081 ns | 0.0068 ns | 2.349 ns | 2.376 ns | 1.00 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 5.161 ns | 0.0469 ns | 0.0439 ns | 5.074 ns | 5.232 ns | 2.18 | 0.01 | - | - | - | - |
| EmitFetcher | 5.181 ns | 0.0524 ns | 0.0490 ns | 5.073 ns | 5.256 ns | 2.18 | 0.03 | - | - | - | - |
| DelegateFetcher | 9.957 ns | 0.1754 ns | 0.1641 ns | 9.701 ns | 10.243 ns | 4.22 | 0.07 | - | - | - | - |
| Reflection | 215.519 ns | 0.7459 ns | 0.6977 ns | 213.798 ns | 216.511 ns | 90.86 | 0.29 | 0.0038 | - | - | 64 B |
| Method | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.000 | 0.00 | - | - | - | - |
| DuckTypeInterface | 4.0533 ns | 0.1463 ns | 0.4199 ns | 4.1939 ns | 2.6805 ns | 4.9533 ns | 1.095 | 0.07 | - | - | - | - |
| DuckTypeAbstract | 3.8792 ns | 0.0550 ns | 0.0514 ns | 3.9012 ns | 3.7611 ns | 3.9309 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.9063 ns | 0.0546 ns | 0.0511 ns | 3.9051 ns | 3.7578 ns | 3.9538 ns | 1.007 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 12.7433 ns | 0.2835 ns | 0.6572 ns | 13.0110 ns | 11.1596 ns | 13.6258 ns | 3.222 | 0.21 | 0.0014 | - | - | 24 B |
| EmitFetcher | 11.2177 ns | 0.2420 ns | 0.4110 ns | 11.2254 ns | 10.5157 ns | 12.1097 ns | 2.898 | 0.13 | 0.0014 | - | - | 24 B |
| DelegateFetcher | 15.0292 ns | 0.0974 ns | 0.0864 ns | 15.0117 ns | 14.9219 ns | 15.2370 ns | 3.877 | 0.06 | 0.0014 | - | - | 24 B |
| Reflection | 226.4618 ns | 1.1025 ns | 0.9774 ns | 226.7582 ns | 223.5496 ns | 227.3624 ns | 58.419 | 0.91 | 0.0052 | - | - | 88 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0162 ns | 0.0024 ns | 0.0023 ns | 0.0127 ns | 0.0196 ns | 0.01 | 0.00 | - | - | - | - |
| DuckTypeInterface | 1.6780 ns | 0.0035 ns | 0.0033 ns | 1.6705 ns | 1.6825 ns | 1.20 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 1.4006 ns | 0.0050 ns | 0.0046 ns | 1.3933 ns | 1.4075 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 1.3839 ns | 0.0032 ns | 0.0025 ns | 1.3799 ns | 1.3882 ns | 0.99 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.4193 ns | 0.0225 ns | 0.0211 ns | 4.3882 ns | 4.4517 ns | 3.16 | 0.02 | - | - | - | - |
| EmitFetcher | 4.4563 ns | 0.0221 ns | 0.0207 ns | 4.4206 ns | 4.4880 ns | 3.18 | 0.02 | - | - | - | - |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 48.7989 ns | 0.1460 ns | 0.1294 ns | 48.6077 ns | 49.0602 ns | 34.84 | 0.12 | - | - | - | - |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0104 ns | 0.0051 ns | 0.0048 ns | 0.0029 ns | 0.0198 ns | 0.008 | 0.00 | - | - | - | - |
| DuckTypeInterface | 1.6868 ns | 0.0067 ns | 0.0063 ns | 1.6743 ns | 1.6995 ns | 1.216 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 1.3874 ns | 0.0045 ns | 0.0042 ns | 1.3799 ns | 1.3937 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 1.3971 ns | 0.0042 ns | 0.0038 ns | 1.3869 ns | 1.4013 ns | 1.007 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 12.3567 ns | 0.2692 ns | 0.3773 ns | 11.3392 ns | 13.0537 ns | 8.883 | 0.33 | 0.0014 | - | - | 24 B |
| EmitFetcher | 12.7230 ns | 0.2337 ns | 0.2186 ns | 12.1087 ns | 12.9269 ns | 9.170 | 0.15 | 0.0014 | - | - | 24 B |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 74.5795 ns | 0.6475 ns | 0.6057 ns | 73.7307 ns | 75.4323 ns | 53.754 | 0.41 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 1.195 ns | 0.0070 ns | 0.0065 ns | 1.186 ns | 1.205 ns | 0.50 | 0.00 | - | - | - | - |
| DuckTypeInterface | 2.638 ns | 0.0171 ns | 0.0160 ns | 2.610 ns | 2.662 ns | 1.09 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 2.409 ns | 0.0069 ns | 0.0064 ns | 2.392 ns | 2.417 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.411 ns | 0.0056 ns | 0.0053 ns | 2.400 ns | 2.419 ns | 1.00 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.879 ns | 0.0398 ns | 0.0372 ns | 4.816 ns | 4.948 ns | 2.03 | 0.02 | - | - | - | - |
| EmitFetcher | 4.798 ns | 0.0265 ns | 0.0248 ns | 4.756 ns | 4.840 ns | 1.99 | 0.01 | - | - | - | - |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 62.681 ns | 0.1221 ns | 0.1142 ns | 62.487 ns | 62.922 ns | 26.02 | 0.08 | - | - | - | - |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0161 ns | 0.0066 ns | 0.0058 ns | 0.0069 ns | 0.0277 ns | 0.004 | 0.00 | - | - | - | - |
| DuckTypeInterface | 4.1358 ns | 0.1109 ns | 0.1442 ns | 3.6628 ns | 4.2307 ns | 1.028 | 0.04 | - | - | - | - |
| DuckTypeAbstract | 3.9717 ns | 0.0101 ns | 0.0085 ns | 3.9483 ns | 3.9830 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.9130 ns | 0.0182 ns | 0.0171 ns | 3.8800 ns | 3.9475 ns | 0.985 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 10.2799 ns | 0.1900 ns | 0.1777 ns | 10.1394 ns | 10.6424 ns | 2.590 | 0.05 | 0.0014 | - | - | 24 B |
| EmitFetcher | 10.2794 ns | 0.1665 ns | 0.1710 ns | 10.0566 ns | 10.6314 ns | 2.586 | 0.05 | 0.0014 | - | - | 24 B |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 78.7027 ns | 0.2133 ns | 0.1891 ns | 78.3381 ns | 78.9225 ns | 19.823 | 0.06 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | 0.0042 ns | 0.0042 ns | 0.0039 ns | 0.0028 ns | 0.0000 ns | 0.0118 ns | 0.002 | 0.00 | - | - | - | - |
| DuckTypeInterface | 2.4260 ns | 0.0095 ns | 0.0089 ns | 2.4228 ns | 2.4145 ns | 2.4431 ns | 1.415 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 1.7151 ns | 0.0077 ns | 0.0072 ns | 1.7147 ns | 1.7045 ns | 1.7298 ns | 1.000 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 1.7322 ns | 0.0082 ns | 0.0077 ns | 1.7330 ns | 1.7175 ns | 1.7472 ns | 1.010 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 48.6474 ns | 0.6056 ns | 0.5665 ns | 48.8195 ns | 46.8674 ns | 49.2839 ns | 28.364 | 0.35 | 0.0067 | - | - | 112 B |
| EmitFetcher | 48.7790 ns | 0.1421 ns | 0.1186 ns | 48.7748 ns | 48.5905 ns | 49.0109 ns | 28.432 | 0.14 | 0.0067 | - | - | 112 B |
| DelegateFetcher | NA | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 351.2802 ns | 0.9316 ns | 0.8258 ns | 351.4524 ns | 349.1993 ns | 352.0959 ns | 204.823 | 0.96 | 0.0091 | - | - | 152 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 2.671 ns | 0.0046 ns | 0.0043 ns | 2.666 ns | 2.681 ns | 1.11 | 0.00 | - | - | - | - |
| DuckTypeAbstract | 2.408 ns | 0.0077 ns | 0.0072 ns | 2.398 ns | 2.422 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.154 ns | 0.0070 ns | 0.0065 ns | 2.145 ns | 2.166 ns | 0.89 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.444 ns | 0.0162 ns | 0.0144 ns | 4.421 ns | 4.469 ns | 1.85 | 0.01 | - | - | - | - |
| EmitFetcher | 4.427 ns | 0.0241 ns | 0.0225 ns | 4.398 ns | 4.470 ns | 1.84 | 0.01 | - | - | - | - |
| DelegateFetcher | 6.422 ns | 0.0151 ns | 0.0134 ns | 6.402 ns | 6.439 ns | 2.67 | 0.01 | - | - | - | - |
| Reflection | 106.718 ns | 0.2564 ns | 0.2273 ns | 106.414 ns | 107.070 ns | 44.31 | 0.16 | - | - | - | - |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 2.881 ns | 0.0089 ns | 0.0083 ns | 2.863 ns | 2.891 ns | 1.19 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 2.413 ns | 0.0105 ns | 0.0099 ns | 2.388 ns | 2.426 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.415 ns | 0.0088 ns | 0.0074 ns | 2.397 ns | 2.426 ns | 1.00 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 12.329 ns | 0.2724 ns | 0.2548 ns | 11.700 ns | 12.732 ns | 5.11 | 0.12 | 0.0014 | - | - | 24 B |
| EmitFetcher | 12.127 ns | 0.2682 ns | 0.4482 ns | 10.431 ns | 12.552 ns | 4.99 | 0.19 | 0.0014 | - | - | 24 B |
| DelegateFetcher | 14.618 ns | 0.2838 ns | 0.2655 ns | 14.230 ns | 14.984 ns | 6.06 | 0.10 | 0.0014 | - | - | 24 B |
| Reflection | 170.210 ns | 1.0057 ns | 0.9407 ns | 168.702 ns | 171.906 ns | 70.55 | 0.55 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 3.967 ns | 0.0965 ns | 0.0903 ns | 3.764 ns | 4.097 ns | 1.09 | 0.02 | - | - | - | - |
| DuckTypeAbstract | 3.639 ns | 0.0086 ns | 0.0076 ns | 3.626 ns | 3.652 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.647 ns | 0.0076 ns | 0.0071 ns | 3.638 ns | 3.657 ns | 1.00 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.728 ns | 0.1222 ns | 0.1143 ns | 4.503 ns | 4.838 ns | 1.30 | 0.03 | - | - | - | - |
| EmitFetcher | 4.765 ns | 0.1213 ns | 0.1075 ns | 4.393 ns | 4.803 ns | 1.31 | 0.03 | - | - | - | - |
| DelegateFetcher | 10.804 ns | 0.2419 ns | 0.2971 ns | 9.875 ns | 11.082 ns | 2.97 | 0.09 | - | - | - | - |
| Reflection | 190.189 ns | 1.3800 ns | 1.2908 ns | 188.956 ns | 193.633 ns | 52.23 | 0.36 | 0.0038 | - | - | 64 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 3.686 ns | 0.0158 ns | 0.0148 ns | 3.660 ns | 3.708 ns | 1.02 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 3.612 ns | 0.0239 ns | 0.0224 ns | 3.589 ns | 3.652 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.628 ns | 0.0100 ns | 0.0078 ns | 3.614 ns | 3.639 ns | 1.00 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 11.522 ns | 0.3087 ns | 0.9103 ns | 10.283 ns | 13.249 ns | 3.02 | 0.20 | 0.0014 | - | - | 24 B |
| EmitFetcher | 10.236 ns | 0.2166 ns | 0.4015 ns | 9.821 ns | 11.229 ns | 2.89 | 0.10 | 0.0014 | - | - | 24 B |
| DelegateFetcher | 14.316 ns | 0.1558 ns | 0.1457 ns | 13.995 ns | 14.607 ns | 3.96 | 0.05 | 0.0014 | - | - | 24 B |
| Reflection | 207.938 ns | 1.0840 ns | 1.0139 ns | 206.318 ns | 210.046 ns | 57.57 | 0.50 | 0.0052 | - | - | 88 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 3.147 ns | 0.0216 ns | 0.0191 ns | 3.125 ns | 3.180 ns | 1.30 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 2.420 ns | 0.0050 ns | 0.0045 ns | 2.408 ns | 2.425 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.407 ns | 0.0151 ns | 0.0126 ns | 2.387 ns | 2.432 ns | 0.99 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 4.480 ns | 0.0549 ns | 0.0487 ns | 4.415 ns | 4.588 ns | 1.85 | 0.02 | - | - | - | - |
| EmitFetcher | 4.401 ns | 0.0182 ns | 0.0162 ns | 4.366 ns | 4.428 ns | 1.82 | 0.01 | - | - | - | - |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 49.517 ns | 0.2291 ns | 0.2143 ns | 49.099 ns | 49.789 ns | 20.48 | 0.09 | - | - | - | - |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 2.847 ns | 0.0154 ns | 0.0137 ns | 2.814 ns | 2.864 ns | 1.20 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 2.381 ns | 0.0164 ns | 0.0137 ns | 2.358 ns | 2.402 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 2.396 ns | 0.0074 ns | 0.0069 ns | 2.382 ns | 2.408 ns | 1.01 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 11.441 ns | 0.2568 ns | 0.6584 ns | 10.388 ns | 13.203 ns | 4.99 | 0.27 | 0.0014 | - | - | 24 B |
| EmitFetcher | 12.052 ns | 0.2697 ns | 0.4652 ns | 10.618 ns | 12.944 ns | 5.12 | 0.26 | 0.0014 | - | - | 24 B |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 81.354 ns | 0.9989 ns | 0.8855 ns | 79.770 ns | 82.538 ns | 34.14 | 0.50 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 3.605 ns | 0.0140 ns | 0.0117 ns | 3.578 ns | 3.619 ns | 0.99 | 0.00 | - | - | - | - |
| DuckTypeAbstract | 3.649 ns | 0.0149 ns | 0.0140 ns | 3.625 ns | 3.675 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.656 ns | 0.0169 ns | 0.0158 ns | 3.629 ns | 3.676 ns | 1.00 | 0.00 | - | - | - | - |
| ExpressionTreeFetcher | 4.772 ns | 0.0397 ns | 0.0371 ns | 4.715 ns | 4.816 ns | 1.31 | 0.01 | - | - | - | - |
| EmitFetcher | 4.822 ns | 0.0209 ns | 0.0174 ns | 4.784 ns | 4.858 ns | 1.32 | 0.01 | - | - | - | - |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 61.724 ns | 0.2886 ns | 0.2559 ns | 61.262 ns | 62.284 ns | 16.91 | 0.10 | - | - | - | - |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 3.701 ns | 0.0248 ns | 0.0207 ns | 3.673 ns | 3.729 ns | 1.02 | 0.01 | - | - | - | - |
| DuckTypeAbstract | 3.633 ns | 0.0218 ns | 0.0182 ns | 3.605 ns | 3.663 ns | 1.00 | 0.00 | - | - | - | - |
| DuckTypeVirtual | 3.635 ns | 0.0262 ns | 0.0232 ns | 3.587 ns | 3.666 ns | 1.00 | 0.01 | - | - | - | - |
| ExpressionTreeFetcher | 10.347 ns | 0.1572 ns | 0.1393 ns | 10.118 ns | 10.510 ns | 2.85 | 0.04 | 0.0014 | - | - | 24 B |
| EmitFetcher | 10.958 ns | 0.2460 ns | 0.5188 ns | 10.207 ns | 12.344 ns | 3.00 | 0.15 | 0.0014 | - | - | 24 B |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 72.224 ns | 0.4226 ns | 0.3953 ns | 71.470 ns | 72.778 ns | 19.87 | 0.19 | 0.0014 | - | - | 24 B |
| Method | Mean | Error | StdDev | Min | Max | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Direct | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| DuckTypeInterface | 59.46 ns | 0.536 ns | 0.476 ns | 58.59 ns | 60.31 ns | 1.03 | 0.01 | 0.0067 | - | - | 112 B |
| DuckTypeAbstract | 57.49 ns | 0.568 ns | 0.531 ns | 56.77 ns | 58.35 ns | 1.00 | 0.00 | 0.0067 | - | - | 112 B |
| DuckTypeVirtual | 56.76 ns | 0.176 ns | 0.164 ns | 56.50 ns | 56.99 ns | 0.99 | 0.01 | 0.0067 | - | - | 112 B |
| ExpressionTreeFetcher | 48.86 ns | 0.301 ns | 0.281 ns | 48.43 ns | 49.32 ns | 0.85 | 0.01 | 0.0067 | - | - | 112 B |
| EmitFetcher | 49.22 ns | 0.565 ns | 0.472 ns | 48.42 ns | 49.90 ns | 0.86 | 0.01 | 0.0067 | - | - | 112 B |
| DelegateFetcher | NA | NA | NA | NA | NA | ? | ? | - | - | - | - |
| Reflection | 355.14 ns | 2.225 ns | 2.082 ns | 351.81 ns | 358.70 ns | 6.18 | 0.06 | 0.0091 | - | - | 152 B |
Thanks to @jetbrains for helping on this development with the licenses for Rider, dotTrace and dotMemory


