.Net 6 : Benchmark performance of JsonSerializer.DeserializeAsyncEnumerable

This should have been part of my earlier post on System.Text.Json Support for IAsyncEnumerable, but it slipped off my mind. So here we are.

To understand the significance of this feature in .Net 6, one need to understand the circumstances under which these might be useful. The first of those would be of course, that the we could be consuming the data even as the rest of the JSON is yet to be deserialized.

The significance is further amplified when you are only interested in the some earlier part of the data. Now you do not really need to deserialize the entire JSON (considering it is a huge one), hold it up in your buffers, and then use only a fraction of those. This could provide immense performance boost to the application.

Let us compare and benchmark the performance of various methods exposed by System.Text.Json for deserialization and attempt to understand it better.

There will be 3 methods which we would be placing under the hammer.

  • JsonSerializer.Deserialize<T>
  • JsonSerializer.DeserializeAsync<T>
  • JsonSerializer.DeserializeAsyncEnumerable<T>

Let us write some code to benchmark them.

[Benchmark]
public void TestDeseriliaze()
{
    foreach(var item in DeserializeWithoutStreaming().TakeWhile(x => x.Id < DATA_TO_COMSUME))
    {
        // DoSomeWork
    }
}

public IEnumerable<Data> DeserializeWithoutStreaming()
{
    var deserializedData = JsonSerializer.Deserialize<IEnumerable<Data>>(serializedString);
    return deserializedData;
}

[Benchmark]
public async Task TestDeseriliazeAsync()
{
    foreach (var item in (await DeserializeAsync()).TakeWhile(x => x.Id < DATA_TO_COMSUME))
    {
        // DoSomeWork
    }
}

public async Task<IEnumerable<Data>> DeserializeAsync()
{
    var memStream = new MemoryStream(Encoding.UTF8.GetBytes(serializedString));
    var deserializedData = await JsonSerializer.DeserializeAsync<IEnumerable<Data>>(memStream);
    return deserializedData;
}



[Benchmark]
public async Task TestDeserializeAsyncEnumerable()
{
    await foreach (var item in DeserializeWithStreaming().TakeWhile(x => x.Id < DATA_TO_COMSUME))
    {
        // DoSomeWork
    }
}

public async IAsyncEnumerable<Data> DeserializeWithStreaming()
{
    using var memStream = new MemoryStream(Encoding.UTF8.GetBytes(serializedString));
    await foreach(var item in  JsonSerializer.DeserializeAsyncEnumerable<Data>(memStream))
    {
        yield return item;
    }
}

Scenario 1 : Consuming only first 20% of the JSON Data

The first scenario we need to consider is when only a fairly small amount of the JSON data is consumed, say the first 20% of the data. While Deserialize<T> and DeserializeAsync would need to deserialize the entire JSON, even if the client would consume only the first 20% of that data, on other hand, DeserializeAsyncEnumerable would deserialize on-demand. This is evident in the benchmark results as well, where the performance of the DeserializeAsyncEnumerable is almost 3 times better.

MethodMeanErrorStdDev
TestDeseriliaze4.810 ms0.0952 ms0.2573 ms
TestDeseriliazeAsync5.166 ms0.1008 ms0.1161 ms
TestDeserializeAsyncEnumerable1.531 ms0.0305 ms0.0825 ms

Scenario 2: Consuming about 80% of the JSON Data

In the second scenario, we will consider when the client consume 80% of data. As one could assume, the now a larger part of JSON data has to be consumed and hence the performance margin decreases.

MethodMeanErrorStdDev
TestDeseriliaze4.960 ms0.0974 ms0.1877 ms
TestDeseriliazeAsync5.238 ms0.0997 ms0.1297 ms
TestDeserializeAsyncEnumerable4.851 ms0.0859 ms0.0804 ms

This is expected too, as more of the JSON is deserialized the performance difference is hardly significant, if not non-existent. But still, there is an advantage of using the DeserializeAsyncEnumerable – you would not have to wait for the entire JSON to be deserialized, the on-demand streaming approach allows you to consume the data as soon parts of JSON are deserialized.

I felt this is a huge improvement, especially when the concerned JSON is significantly large. Like many others, I am equally excited to see the improvements in .Net in recent years and is looking forward for the release of .Net 6.

.Net 6 : System.Text.Json support for IAsyncEnumerable

As the Preview 4 of .Net 6 becomes available, one of the things that excites me is the System.Text.Json support for IAsyncEnumerable. The IAsyncEnumerable, introduced in .Net Core 3 and C# 8, enables us to iterate over async Enumerables. The newer version extends this support to the System.Text.Json.

Consider the following data.

[{"Id":0,"Value":"915777539"},{"Id":1,"Value":"1332243482"},{"Id":2,"Value":"306207588"},
 {"Id":3,"Value":"1413388423"},{"Id":4,"Value":"2145941621"},{"Id":5,"Value":"1041779876"},
 {"Id":6,"Value":"1121436961"},{"Id":7,"Value":"520045044"},{"Id":8,"Value":"1357859915"},
 {"Id":9,"Value":"1340510964"},{"Id":10,"Value":"1183306988"},{"Id":11,"Value":"502467538"},
 {"Id":12,"Value":"31513434"},{"Id":13,"Value":"999086707"},{"Id":14,"Value":"961728759"},
 {"Id":15,"Value":"1756662810"},{"Id":16,"Value":"1018107007"},{"Id":17,"Value":"433502262"},
 {"Id":18,"Value":"1784715926"},{"Id":19,"Value":"1418088822"},{"Id":20,"Value":"645106286"},
 {"Id":21,"Value":"1720929044"},{"Id":22,"Value":"1102142546"},{"Id":23,"Value":"2138442183"},
 {"Id":24,"Value":"208176799"},{"Id":25,"Value":"1700100438"},{"Id":26,"Value":"769308703"},
 "Id":27,"Value":"1558581057"},{"Id":28,"Value":"352810944"},{"Id":29,"Value":"299925316"}]

we could now write a streaming deserialization method using the JsonSerializer.DeserializeAsyncEnumerable. For example.

public async IAsyncEnumerable<T> DeserializeStreaming<T>(string data)
{
    using var memStream = new MemoryStream(Encoding.UTF8.GetBytes(data));

    await foreach(var item in JsonSerializer.DeserializeAsyncEnumerable<T>(memStream))
    {
        yield return item;
        await Task.Delay(1000);
    }
}

// Data
public class Data
{
    public int Id { get; set; }
    public string Value { get; set; }

}

The async streams of deserialized data provides an oppurtunity to deserialize on demand, which could be great addition particularly deserializing large data.

var instance = new StreamingSerializationTest();
await foreach (var item in instance.DeserializeStreaming<Data>(dataString))
{
    Console.WriteLine($"Data Item: {nameof(Data.Id)}={item.Id} , {nameof(Data.Value)}={item.Value}");

    if(item.Id > 5)
    {
        break;
    }
}

As you can observe in the output below, this would deserialiaze only on-demand.

Streaming Deserialize Demo
Inside Deserializing..
Data Item: Id=0 , Value=915777539
Inside Deserializing..
Data Item: Id=1 , Value=1332243482
Inside Deserializing..
Data Item: Id=2 , Value=306207588
Inside Deserializing..
Data Item: Id=3 , Value=1413388423
Inside Deserializing..
Data Item: Id=4 , Value=2145941621
Inside Deserializing..
Data Item: Id=5 , Value=1041779876
Inside Deserializing..
Data Item: Id=6 , Value=1121436961

As the moment, the Deseriliazation is severely limited to root level Json Arrays, but I guess that would over time as .Net 6 reaches release. Let us take a look at the serialization as well now. Turns out that is easy as well.

private async IAsyncEnumerable<Data> Generate(int maxItems)
{
    var random = new Random();
    for (int i = 0; i < maxItems; i++)
    {
        yield return new Data
        {
            Id = i,
            Value = random.Next().ToString()
        };
    }
}

public async Task SerializeStream()
{
    using var stream = Console.OpenStandardOutput();
    var data = new { Data = Generate(30) };
    await JsonSerializer.SerializeAsync(stream, data);
}

At this point, am not quite excited about streaming Serialization as I am about streaming Deserilization. This is because of the lack of usecase it might support. But am not denying there could be usecases, and over the time, I might be equally excited about it as well.

Complete sample of the code in this demo could be found in my Github

We will continue exploring the .Net 6 features in the upcoming posts as well. Until then, enjoy coding…

How CLR Handles Static, Non-Virtual Instance, and Virtual Instance method calls

How does method execution differs when CLR handles static, instance and virtual instance methods ? To answer them, one needs to begin by understanding a bit more on how CLR handles Managed Heap during execution of a method.

Memory Allocation in Managed Heap

When the application execution begins, as the CLR gets loaded, the thread stack and managed heap gets allocated. Prior to method execution, JIT (Just In Time) Compiler converts the IL code to native instructions. At this moment, it also detects all the types used in the method and also loads all the required/dependend assemblies needed to support the execution.

The CLR also gathers information about the data types involved from the metadata and create the required Data structures. Each time a new Type is encountered, a data structure representing Type Object is created. The Type Object contains two special fields called Type Object Pointer and Sync Block Index. The Type Object also contains static fields and a method reference table. The Method table contains an entry for each method exposed by the type.

For each instance of a type, an instance object data structure is create in the Managed Heap. The instance object would memory space for storing the instance fields in the type. Similiar to the Type Object , the instance object would also contain the two special fields – Type Object Pointer and Sync Block Index.

The Type Object Pointer of the instance object points to the corresponding type object. At this point, one might wonder what would the Type Object Pointer of the type object point to ? Well, it points to a special type object of type System.Type. The next question that might arise in your mind would be, what would type object pointer of the System.Type type object refers to ? The answer is – it refers to self. Interesting.

Once the local variables are created in Thread Stack, the compiled native instruction is executed. After the method exection completes, the CPU instruction is set to the return address.

A common question that might arise would be what happens when a new object is created using the new operator ? During the object creation, the CLR calculates the size of instance fields in the type. It then allocates memory for the calculated size, including fields for Type Object Pointer and Sync Block Index. It also resets the memory to zero. At this point, the constructor is invoked and any fields that could be initialized are assign initial values. It then returns the reference(address) to the newly created object.

Let us now see how CLR handles method execution and how the data structures we discussed in earlier section are related.

Static Method Execution

During the execution of Static Methods, CLR locates the concerned Type’s Type Object data structure in the heap (it would create it if not already created). It then proceed to locate the entry in the method table for the method to be invoked. The compiler then JIT Compiles the method code (only if required – if the method has already been invoked and the native code is already available, this step is skipped) and start executing the native code.

Non Virtual Instance Methods

The execution of a non-virtual instance method is slightly different from the execution of Static Method. It has couple of additional steps.

During the execution of non-virtual instance methods, the compiler detects the Type Object that corresponds to the type of variable being used in the method call. If the method entry is not found in the method table, then it walks through the class heirarchy, checking each of the base type objects for an entry in the method table.

Once it finds the method, follows the steps mentioned for static method. It JIT compiles (only if required) the method code and invokes the native code.

Virtual Instance Method

In the case of virtual instance methods, the compiler begins by refering to the address of instance object the variable points to. The Type object pointer of the instance object would be pointing to the actual type of the object. It then locates the method entry in the Method table, JIT compiles if required and start executing the code.

A summary of the whole process is visualized in the sketch notes below.

Roslyn Analyzer : Analyzing Comments

One of the things one might encounter quite early while writing a Roslyn Code analyzer for comments is it is slightly different from detection of Syntax Nodes. In fact, it is not a node at all.

Syntax nodes represent syntactic constructs, for example declaration, statements, clauses and expressions. A Comment do not quite fall in the same category. It is rather a Syntax Trivia. Syntax Trivia are, as Microsoft states, largely non-significant components such as whitespaces, comments and preprocessor directives. Due to their rather insignificant presence, they are not included as child nodes of Syntax Tree. However, since they are still important in their own ways, they are still part of the Syntax Tree.

For the same reason, you would need to register a SyntaxTreeAction using RegisterSyntaxTreeAction rather SyntaxNodeAction using RegisterSyntaxNodeAction. For analyzing comments, our typical Initialize() method would like the following.

public override void Initialize(AnalysisContext context)
{
    context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.None);
    context.EnableConcurrentExecution();

    context.RegisterSyntaxTreeAction(AnalyzeComment);
}

The next step involves parsing the SingleLineCommentTrivia and MultiLineCommentTrivia trivias from the syntax tree. You could achieve this with a simple Linq Query.

private void AnalyzeComment(SyntaxTreeAnalysisContext context)
{
    SyntaxNode root = context.Tree.GetCompilationUnitRoot(context.CancellationToken);
    var commentTrivias = root.DescendantTrivia()
                            .Where(x => x.IsKind(SyntaxKind.SingleLineCommentTrivia) || x.IsKind(SyntaxKind.MultiLineCommentTrivia));

    // Rest of the code
}

That’s all you need. Didn’t that turn up quite easy. I wish there was a easy to parse the actual comment out of Trivia, however, unfortunately, I haven’t found one yet (not sure if one exist). At the moment, the most likely way to use the ToString() method. This would in fact, include comment characters as well, which you can parse out using Regex or simple string transformations.

Why Initialize Collection Size

In possibly every code base you might have seen, usage of Collections would have been a common sight. The introduction of Generic Collections in early stages of evolutin of language has made is all the more favourite of developers comparing to the non-generic cousins that existed before. One of the most common patterns seen in any code base is as follows.

var persons = GetPersonList();
var studentList = new List<Student>();
foreach(var person in persons)
{
    studentList.Add(new Student
    {
        FirstName = person.FirstName,
        LastName = person.LastName
    });
}

At the first glance, there is nothing wrong with the code. In fact, it works well too. Unlike arrays, one doesn’t need to declare the size of List beforehand, and it sort of magically does the trick to expand itself. However, there is a hidden problem caused due to the optimized way the Collection is implemented to magically expand.

Beneath the List declaration, there is still an array, which is made to resize according to the ever growing requirements of the Collection. This is done in the Add method, which is defined as

public void Add(T item) 
{
    if (_size == _items.Length) EnsureCapacity(_size + 1);
    _items[_size++] = item;
    _version++;
}

private void EnsureCapacity(int min) 
{
    if (_items.Length < min) {
        int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;

        if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
        if (newCapacity < min) newCapacity = min;
        Capacity = newCapacity;
    }
}

The Add() method checks if the array is full, and if so, it calls the EnsureCapacity method to double the Capacity.

The resizing of course happens in the Capacity Property.

public int Capacity 
{
    get {
        Contract.Ensures(Contract.Result<int>() >= 0);
        return _items.Length;
    }
    set {
        if (value < _size) {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        }
        Contract.EndContractBlock();

        if (value != _items.Length) {
            if (value > 0) {
                T[] newItems = new T[value];
                if (_size > 0) {
                    Array.Copy(_items, 0, newItems, 0, _size);
                }
                _items = newItems;
            }
            else {
                _items = _emptyArray;
            }
        }
    }
}

The key take away from the Add/EnsureCapcity methods is that every time the size of array is breached, the capacity of the array is doubled. This leads to couple of undesired things.

  • Expensive operation to resize the array

As the List grows, there would innumerous expensive resizing operations, which is quite undesired.

  • Possibility that a lot of memory spaces left allocated but unused.

Consider if the number of Person in the personList is 258. Due to the logic shown above, the Capacity of Array would now 512. That is a whole lot of unused allocated memory space when you are working with memory intensive application.

// Default Behavior
Console.WriteLine($"StudentList(Count={studentList.Count},Capacity={studentList.Capacity})");
// Output
StudentList(Count=258,Capacity=512)

The ideal way to counter this would be to use overloaded constructor and initialize the size of array.

var studentList = new List<Student>(persons.Count());

This would reduce the need for resizing of internal array.

// With Collection Size Iniitialized as above
 Console.WriteLine($"StudentList(Count={studentList.Count},Capacity={studentList.Capacity})");
// Output
StudentList(Count=258,Capacity=258)

Of course there could be places where you might not be having the convenience of knowing the collection size beforehand. But still, if you are able to be pick an initial size well, you could eliminate or reduce the need to resize the array.

MahApps HamburgerMenu and Caliburn Micro

MahApps is probably one of the most used UI library among WPF developers, with a galaxy of great controls. Despite that, recently I was surprised to see lack of proper example for Hamburger Menu control, particulary MVVM based. I was also more keen to know how to make best use of capabilities of Caliburn Micro along the way.

Here is how I ended up achieving my objectives.

XAML : Control, Content, ItemTemplate and HeaderTemplate

The first step would be to define the Control in Xaml, along with desired ContendTemplate,ItemTemplate and HeaderTemplate.

<mah:HamburgerMenu x:Name="Menu" DisplayMode="CompactOverlay" SelectedItem="{Binding ActiveItem,Converter={StaticResource SelectedItemConverter}}"
           ItemsSource="{Binding MenuItems,Converter={StaticResource MenuConverter}}"
           cal:Message.Attach="[Event ItemClick]=[Action MenuSelectionChanged($source,$eventArgs)]"
           HamburgerMenuHeaderTemplate="{StaticResource MenuHeaderTemplate}"
           ItemTemplate="{StaticResource MenuItemTemplate}">
    <mah:HamburgerMenu.Content>
       <ContentControl Grid.Column="0" Grid.Row="1" x:Name="ActiveItem" />
    </mah:HamburgerMenu.Content>
</mah:HamburgerMenu>

As you would have noticed couple of converters in here. We will get to that in a moment, but first let us define our MenuItemTemplate and MenuHeaderTemplate.

<!-- Menu Header Template -->
<DataTemplate x:Key="MenuHeaderTemplate">
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"  FontSize="16"  Foreground="White"  Text="Sample App" />
</DataTemplate>

<!-- Menu Item Template -->
<DataTemplate x:Key="MenuItemTemplate">
    <Grid x:Name="RootGrid" Height="48" Background="Transparent">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="48" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ContentControl Grid.Column="0"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Content="{Binding Icon}"
            Focusable="False" />
        <TextBlock Grid.Column="1"
           VerticalAlignment="Center"
           FontSize="16"
           Text="{Binding Label}" />
    </Grid>
</DataTemplate>

At this point, we need to create our ViewModels for each of the menu items. As we notice from the templates above, there are couple of fields which are required for each of Menu Items – a Title, and a Icon (_Icon is not quite mandatory, depending on the type of Menu Item you are creating).

Destination ViewModels

Let us go ahead and define our ViewModels for Menu Items.

public class PageViewModelBase : Screen
{
    public virtual string Title { get; }
    public virtual object Icon { get; }
}
public class HomePageViewModel : PageViewModelBase
{
    public override string Title => "Home";
    public override object Icon => new PackIconMaterial { Kind = PackIconMaterialKind.Home };
}
public class ProfilePageViewModel : PageViewModelBase
{
    public override string Title => "Profile";
    public override object Icon => new PackIconMaterial { Kind = PackIconMaterialKind.AccountStar };
}

In the above example, we are using the MahApps.Metro.IconPack for Icons, but that is only an implementation detail which could can easily vary. For sake of simplicity, I have omitted the Views here, but that could be found in the example solution given in the end of this article.

The Glue : ValueConverters and ActiveItem

We now have different ViewModels defined, and it is time to create the dynamic collection to bind to our HamburgerMenu Control. So, in our ShellViewModel, we will do the following.

public ShellViewModel()
{
    MenuItems = new List<PageViewModelBase>
    {
        new HomePageViewModel(),
        new ProfilePageViewModel()
    };
}

public IEnumerable<PageViewModelBase> MenuItems { get; }

We are almost there, and now as the final step, we need to write our converters. There are two converters involved,

  • PageToMenuItemConverter – Converts from ViewModel Collection to HamburgerMenuIconItem.
  • SelectedItemConverter – Parse the ViewModel from SelectedItem
public class PageToMenuItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is IEnumerable<PageViewModelBase> nmItemCollection)
        {
            return nmItemCollection.Select(item => new HamburgerMenuIconItem
            {
                Tag = item,
                Icon = item.Icon,
                Label = item.Title
            });
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

public class SelectedItemConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is HamburgerMenuIconItem menuItem ? menuItem.Tag : value;
    }
}

That’s all we need. Your menu would be up and running now. You can find the example code in my Github here

A2Z.Net : A – Anonymous Types

This article marks the beginning of a new series of posts, which aims to dig deeper into 26 different features of .Net. For the first article, or the A – I have selected Anonymous Types. I would have chosen asynchronous programming, but I have whole dedicated series on asynchronous programming which could followed in this link.

Introduced in .Net 3.x, Anonymous Types has made the life easy for the developers by handling out the ability to work on an encapsulated type, without having to actually define one. I should say encapsulate is a wrong word here (but have used it so that I could highlight why) because you cannot place any behavior with the properties.

Anonymous Types and Syntax

Anonymous Type provides an easy way to encapsulate a set of properties without having to explicitly define a type. Notice that I used the word explicitly here – that is because the compiler creates the type for you under the hood. We will look into what happens behind the scenes a little later, to begin with, let us introduce the syntax of defining an anonymous type.

var user = new
{
    UserName ="Anu Viswan",
    Age = userRecord.Age,
    JoiningDate= DateTime.Now
};

The above code uses object initializer (without having to specify the data type) to create an instance of an anonymous type initialized with 3 properties – namely UserName(string),Age(int), and JoiningDate (DateTime). You could also create an anonymous type.

As I mentioned earlier, the compiler generates a type under the hood and ensure the code is still statically typed.

Since the type of anonymous Type is known statically, they must be stored using variables with var allowing type inference. You could also store them as object, but that would defeat the whole purpose of anonymous types.

In addition to the creation syntax mentioned above, framework also provides another way initializing an anonymous type. This syntax is known as projection initializer, and it allows you to use the property/field names from somewhere else.

var person = new Person
{
    FirstName = "Anu",
    LastName = "Viswan",
    Age = 36
};

var user = new
{
    person.FirstName,
    person.Age,
};

The above code uses a part of type Person to create an anonymous type. In this case, as you can notice, you are not explictly providing names for properties, instead, they uses the same name as the Person. This is of course equavalent of writing as

var user = new
{
    FirstName = person.FirstName,
    Age = person.Age
};

The projection initializer syntax is highly useful in Linq queries when you need to project a subset of a query or combine properties from multiple objects. For Example,

var personList = new List<Person>
{
	new Person {UserName="Anu Viswan",    Age = 36},
	// Other Persons
};

var employeeList = new List<Employee>
{
    new Employee{UserName="Anu Viswan",JoiningDate=new DateTime(2020,2,2)},
    // Other employee records //
};

var user = employeeList.Join(personList,
							e=>e.UserName,
							p=>p.UserName,
							(e,p)=> new
								{
									e.UserName,
									UserDetail = new  // An example of Nested Anonymous Type
									{
									e.JoiningDate,
									p.Age,
									QueryTimeStamp=DateTime.Now
									}
								});

As you can observe the creation of anonymous types are pretty simple. You could also create a type combining multiple objects as seen in above example. The above code also demonstrates that the anonymous types could be nested. UserDetail is an anonymous type within the user.

Behind the Scenes

Alright, enough of syntax, let us now look behind the scenes now. Let us bring back our first example of anonymous type and see how the type generated by the compiler looks like.

var user = new
{
    UserName = "Anu Viswan",
    Age = 36,
    JoiningDate= DateTime.Now
};

The compiler generated (_generated using ILSpy) type would look like

[CompilerGenerated]
[DebuggerDisplay("\\{ UserName = {UserName}, Age = {Age}, JoiningDate = {JoiningDate} }", Type = "<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<<UserName>j__TPar, <Age>j__TPar, <JoiningDate>j__TPar>
{
	[DebuggerBrowsable(DebuggerBrowsableState.Never)]
	private readonly <UserName>j__TPar <UserName>i__Field;

	[DebuggerBrowsable(DebuggerBrowsableState.Never)]
	private readonly <Age>j__TPar <Age>i__Field;

	[DebuggerBrowsable(DebuggerBrowsableState.Never)]
	private readonly <JoiningDate>j__TPar <JoiningDate>i__Field;

	public <UserName>j__TPar UserName => <UserName>i__Field;

	public <Age>j__TPar Age => <Age>i__Field;

	public <JoiningDate>j__TPar JoiningDate => <JoiningDate>i__Field;

	[DebuggerHidden]
	public <>f__AnonymousType0(<UserName>j__TPar UserName, <Age>j__TPar Age, <JoiningDate>j__TPar JoiningDate)
	{
		<UserName>i__Field = UserName;
		<Age>i__Field = Age;
		<JoiningDate>i__Field = JoiningDate;
	}

	[DebuggerHidden]
	public override bool Equals(object value)
	{
		// Hidden : Will be discussed later
	}

	[DebuggerHidden]
	public override int GetHashCode()
	{
		// Hidden : Will be discussed later
	}

	[DebuggerHidden]
	public override string ToString()
	{
		// Hidden : Will be discussed later
	}
}


Characteristics of Generated Code

Let us break down the generated code and examine it in parts.

It is a Generic Class

As you would have already observed, the generated type is a class, name of which is generated by the compiler and cannot be accessed from your source code.

internal sealed class <>f__AnonymousType0<<UserName>j__TPar, <Age>j__TPar, <JoiningDate>j__TPar>
{
    public <>f__AnonymousType0(<UserName>j__TPar UserName, <Age>j__TPar Age, <JoiningDate>j__TPar JoiningDate)
	{
		<UserName>i__Field = UserName;
		<Age>i__Field = Age;
		<JoiningDate>i__Field = JoiningDate;
	}
}

It is also interesting to note that the generated type is a Generic class, with one type parameter for each of the properties. This would mean that if there is a second string, it would still have a different type parameter than the original one. For example,

var user = new
{
    UserName = "Anu Viswan",
    FirstName = "Anu"
};

The above would translate to

internal sealed class <>f__AnonymousType0<<UserName>j__TPar, <FirstName>j__TPar>
{
}

Note that the class is marked internal and sealed. Now both these characterstics aren’t guaranteered as per Jon Skeet’s book C# in Depth. This is actually interesting, as to know when and why the compiler could not guarante a consistent behavior.

The generated type also has a constructor which accepts parameters which are in consistent with all the properties in the type.

Read Only Properties

The other characterstics of the generated type that is quite obvious is that all properties are read-only. One cannot reassign properties of an anonymous type. If the need arise, you would have to recreate the entire object.

var user = new
{
    UserName = "Anu Viswan",
    Age = 36,
    JoiningDate = DateTime.Now,
};

user.Age = 37; // This line would throw error

user = new  // The correct approach would be recreate
{
    UserName = user.UserName,
    Age = 37,
    JoiningDate = user.JoiningDate,
};

Derieved from System.Object & Overrides Equals()/GetHashCode()

The generated class for anonymous types is derieved from System.Object. It cannot be, hence, cast to any other type other than Object. The generated type also overrides the Equals() and GetHashcode() methods.

public override bool Equals(object value)
{
    <>f__AnonymousType0<<UserName>j__TPar, <Age>j__TPar, <JoiningDate>j__TPar> anon = value as <>f__AnonymousType0<<UserName>j__TPar, <Age>j__TPar, <JoiningDate>j__TPar>;

    return anon != null && EqualityComparer<<UserName>j__TPar>.Default.Equals(<UserName>i__Field, anon.<UserName>i__Field) && EqualityComparer<<Age>j__TPar>.Default.Equals(<Age>i__Field, anon.<Age>i__Field) && EqualityComparer<<JoiningDate>j__TPar>.Default.Equals(<JoiningDate>i__Field, anon.<JoiningDate>i__Field);
}

public override int GetHashCode()
{
    return ((459989953 * -1521134295 + EqualityComparer<<UserName>j__TPar>.Default.GetHashCode(<UserName>i__Field)) * -1521134295 + EqualityComparer<<Age>j__TPar>.Default.GetHashCode(<Age>i__Field)) * -1521134295 + EqualityComparer<<JoiningDate>j__TPar>.Default.GetHashCode(<JoiningDate>i__Field);
}

These ensures that two instances of AnonymousTypes are equal only if all the properties are equal. Do note that the exact implementation of GetHashCode() might also vary. For example,

var user = new
{
    UserName = "Anu Viswan",
    Age = 36,
    JoiningDate = new DateTime(2020,10,10),
};

var anotherInstance = new
{
    UserName = "Anu Viswan",
    Age = 36,
    JoiningDate = new DateTime(2020, 10, 10),
};

Console.WriteLine($"user & anotherInstance - Equality :{user.Equals(anotherInstance)}"); // True

Reuse of Anonymous Types

If two anonymoys types are created with same Property Names, in same order and type, then the compiler would treat the two objects as of same type, ie, essentially reuse the generated type.

For example, the preceeding code would reuse the same generated type.

Console.WriteLine($"user & anotherInstance - Type Equality :{user.GetType() == anotherInstance.GetType()}"); // True

This could verified when we check the generated code.

<>f__AnonymousType0<string, int, DateTime> user = new <>f__AnonymousType0<string, int, DateTime>("Anu Viswan", 36, new DateTime(2020, 10, 10));

<>f__AnonymousType0<string, int, DateTime> anotherInstance = new <>f__AnonymousType0<string, int, DateTime>("Anu Viswan", 36, new DateTime(2020, 10, 10));

However, if you change the order of Properties in either of the anonymous types, the compiler would generate another type. Consider the following code.

 var user = new
 {
     UserName = "Anu Viswan",
     Age = 36,
     JoiningDate = new DateTime(2020,10,10),
 };
  var differentInstance = new
 {
     UserName = "Anu Viswan",
     JoiningDate = new DateTime(2020, 10, 10),
     Age = 36,
 };

As you can observe, while the PropertyNames and Types are preserved in the two anonymous types, the order is changed.The generated code would be as following.

<>f__AnonymousType0<string, int, DateTime> user = new <>f__AnonymousType0<string, int, DateTime>("Anu Viswan", 36, new DateTime(2020, 10, 10));

f__AnonymousType1<string, DateTime, int> differentInstance = new <>f__AnonymousType1<string, DateTime, int>("Anu Viswan", new DateTime(2020, 10, 10), 36);

As seen in the generated code, the compiler generates and use different internal types for the two anonymous types.

This holds true only when the two anonymous types are in the same assembly. If the two anonymous types are defined in two different assemblies, compiler would generate two different types for each. We will explore this later in this article.

Points Of Interest

The above section outlined the characterstics of Anonymous Types. There are however, certain points which is worth noting while learning about Anonymous Types.

Pass as Parameter/ Return Type

Since the generated type is not accessible/addressed by the developer in his code, it to an extend limits the transfer an anonymous types from one method to another as you cannot express the type as Parameter. However, you could make use of Generics to pass the anonymous types around. For example,

 public void Print<T>(T data)
 {
     var properties = typeof(T).GetProperties();
     foreach(var property in properties)
     {
         Console.WriteLine($"{property.Name} = { property.GetValue(data)}");
     }
 }

The compiler here treats the generated type as any reference type in the system. This allows us to use generics to pass anonymous types around.

You could also pass the anonymous type as an object or dynamic parameter as well, however, that would take away any benefits associated to anonymous types.

Similiar Anonymous Types in Two Assemblies

In the earlier section we noticed how the compiler would reuse the same generated type if the Property Names, Order and Types are the same. However, there is a caveat. The generated types are localized to the assembly.

If the two types resides in different assembly, then the compiler would generate different Anonymous Types for each of them.

Consider the following scenario.

// Assembly 1
 var user = new
 {
     UserName = "Anu Viswan",
     Age = 36,
     JoiningDate = new DateTime(2020,10,10),
 };
 var bar = new Bar();
 bar.Print(user);


// Assembly 2
public class Bar
{
    public void Print(object data)
    {
        var typeSchema = new { UserName = string.Empty, Age = default(int), JoiningDate = default(DateTime) };
        var castInstance = Cast(typeSchema, data);
        Console.WriteLine(data.GetType() == castInstance.GetType());
    }
    private static T Cast<T>(T typeHolder, Object x) where T : class
    {
        return (T)x;
    }
}

The above casting would raise an InvalidCastException as the two types resides in different assemblies, resulting in compiler generating two different anonymous types.

This would have been a succesful cast if the code resided in the same assembly.

Conclusion

As observed, the implement of Anonymous Types is pretty simple, and so is its usage. The compiler generates a generic class for each unique anonymous type within the assembly. The feature has been extensively used since Linq came along as it allows to create subsets from queries without having to define an explicit type.

The complete code citd in this article is available in my Github.

MemoryCache – AddOrGetExisting Method

MemoryCache provides an easy to use method AddOrGetExisting which provides an easy way to retrive or add data to cache. While it is extremely convenient, it comes off at a cost. Let’s explore it a bit along with alternative.

Note : For the sake of example, let us ignore multi-threading scenarios for the moment.

   public class MemoryCacheRunner
   {
        private MemoryCache _memoryCache;
        private string _uniqueKey = "UniqueKey";
        public MemoryCacheRunner()
        {
            _memoryCache = new MemoryCache("DemoCache");
            _memoryCache.Add(_uniqueKey, new Foo { Name = "Anu Viswan", Age = 36 }, new CacheItemPolicy());
        }
   }

There are two ways we could check if the a particular key exists in the cache and retrieve it (after adding if it is not already present).

Option 1 – Using AddOrGetExisting

public Foo GetFromCacheUsingAddOrGet()
{
    var instance = new Foo { Name = "Anu Viswan", Age = 36 };
    return (Foo)_memoryCache.AddOrGetExisting(_uniqueKey, instance, new CacheItemPolicy());
}

As you can observe, that looks pretty easy and convenient. This is far less code the following approach.

Option 2 – Using Contains/Get

public Foo GetFromCacheUsingContainsAndGet()
{
    if (_memoryCache.Contains(_uniqueKey))
    {
        return (Foo)_memoryCache.Get(_uniqueKey);
    }
    var instance = new Foo { Name = "Anu Viswan", Age = 36 };
    _memoryCache.Add(_uniqueKey, instance, new CacheItemPolicy());
    return instance;
}

That’s definetly a lot more code. But if one was to carefuly observe, Option 2 is infact far more efficient.

In the first approach, you are forced to create an instance of Foo, even if the object exists in the cache. The second approach, however, creates a new instance only if the cache doesn’t contains the specified key.

This could be insignificant when the size of data type is pretty small, but as the size of data increases, one has to be wary of such differences to make your application work optimally.

Stay Open Functionality for Oxyplot Tracker

One of the recent questions on Stackoverflow was about having a Oxyplot tracker that

  • Is evoked only over the Points and NOT line/outside.
  • Stays Open until another point is selected.

The first part could be easily achieved by using a Custom PlotController that Binds the Mouse Down event only the Left Mouse Button and only on Tracks

CustomPlotController = new PlotController();
CustomPlotController.UnbindAll();
CustomPlotController.BindMouseDown(OxyMouseButton.Left, PlotCommands.PointsOnlyTrack);

You could now bind the CustomPlotController with your Xaml as

<oxy:PlotView Model="{Binding MyModel}" Controller="{Binding CustomPlotController}">

The second part needs you to write a Custom TrackerManipulator. The core idea would revolve around override the Completed method in TrackerManipulator, so that the Oxyplot is unable to hide the tracker.

If we were to ensure with the same TrackerManipulator that the trackers is enabled only Points, then the current tracker would be left open until the new tracker is opened at new location by a succeeding click on another point in the graph.

Let us go ahead and write our Custom TrackerManipulator.

public class StaysOpenTrackerManipulator : TrackerManipulator
{
    public StaysOpenTrackerManipulator(IPlotView plotView) : base(plotView)
    {
        Snap = true;
        PointsOnly = true;
    }
    public override void Completed(OxyMouseEventArgs e)
    {
        // Do nothing
    }
}

That’s all you need to achieve the goal. You can find the source code of this post in my Github Repo