Posts Tagged ‘dotnet’

Convert sample Maui app to MVVM

May 1st, 2023

Create base from Maui template

Open Visual studio, create new project from “.NET MAUI App”. Name it “MauiApp1”.

Set target to “Windows Machine” and press play just to make sure all dots are connected.

The start and result are on Github:LosManos/MauiApp1_MVVM.

If you prefer video instead of text James Montemagno has a similar Youtube video.

Plans

Investigate the code.
In MainPage.xaml there is a tight coupling from the xaml file to the code behind through

1
Clicked="OnCounterClicked"
. That method has code like
1
CounterBtn.Text = $"Clicked {count} time";
which means it is tightly coupled with the GUI.

When running the code, the counter and button text, will be updated by the code above.

Let’s get rid of the tight coupling.

Note: I am not satisfied how the click command will be wired up in the final solution. Please comment and help me make it better.

View model

MVVM works by GUI logic writing to an object/data structure (the view model) and the GUI graphic reading from it. And vice verse. It can be compared to a data contract with talking over the wire

This means we can test the logic without having a GUI and the GUI won’t have to rely on complicated GUI logic.

Create a class “MainPageViewModel.cs”, in a new folder “ViewModel”. We want to replace the counter.

To make it easier to react on the changes of the values we will use CommunityToolkit. To make it work the MVVM class must be public and partial. The field must be a field (not a property, and it must be with a leading lower case. Add a counter and a buttonText. Add a method to update the counter and replace the button text.

The reason for the above is that CommunityToolkit creates a Property for every field with ObservableProperty. You can find the rendered code in MauiApp1/Dependencies/.net7.0-xxxx/Analyzers.
I have some reason for the view model to be public but won’t delve into it here.

Install Nuget package CommunityToolkit.MAUI and CommunityToolkit.Mvvm.

(Sorry for the &#91; and &lt;, but I don’t want to dig through WordPress. Just replace with [ and < respectively.)

Class “MainPageViewModel.cs” will look like this:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace MauiApp1.ViewModel;

public partial class MainPageViewModel : ObservableObject
{
    public MainPageViewModel()
    {
        ButtonText = "Click Me";
    }

    &#91;ObservableProperty]
    public int myCount;

    &#91;ObservableProperty]
    public string buttonText;

    &#91;RelayCommand]
    public void IncreaseCount()
    {
        MyCount += 1;

        if (MyCount == 1)
            ButtonText = $"Clicked {MyCount} time";
        else
            ButtonText = $"Clicked {MyCount} times";
    }
}

Pressing play should work now as we only have added a class. Not changed or connected anything.

Connect

As per the readme you received when installing CommunityToolkit we have to manipulate the startup. Make it use the CommunityToolkit. Open MauiProgram.cs and add


1
    .UseMauiCommunityToolkit()

Then we need to wire up the dependency injection. Alas add


1
2
    builder.Services.AddSingleton&lt;ViewModel.MainPageViewModel&gt;();
    builder.Services.AddSingleton&lt;MainPage&gt;();

You will now have something like


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;

namespace MauiApp1;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp&lt;App&gt;()
            .UseMauiCommunityToolkit()
            .ConfigureFonts(fonts =&gt;
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        builder.Services.AddSingleton&lt;ViewModel.MainPageViewModel&gt;();
        builder.Services.AddSingleton&lt;MainPage&gt;();

#if DEBUG
        builder.Logging.AddDebug();
#endif

        return builder.Build();
    }
}

In MainPage.xaml.cs we get rid of the OnCounterClicked method and the counter. We also need to inject the view model to the main page MainPage.xaml.cs. All that is left is:


1
2
3
4
5
6
7
8
9
10
namespace MauiApp1;

public partial class MainPage : ContentPage
{
    public MainPage(ViewModel.MainPageViewModel vm)
    {
        InitializeComponent();
        BindingContext = vm;
    }
}

Do the xaml dance

As we have removed the event handler we also need to remove it from the xaml. Find the button and get rid of “Clicked=”OnCounterClicked””. We also don’t need the name as the code does not reference the button any more. The result looks like


1
2
3
4
5
&lt;Button
  Text="Click me"
  SemanticProperties.Hint="Counts the number of times you click"
  HorizontalOptions="Center"
/&gt;

If you press play now the program will start but nothing will happen if you press play.

Add dynamic button text and the the cryptic command binding to the button


1
2
3
4
5
6
&lt;Button
  Text="{Binding ButtonText}"
  SemanticProperties.Hint="Counts the number of times you click"
  Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainPageViewModel}}, Path=IncreaseCountCommand}"
  HorizontalOptions="Center"
/&gt;

The above will not work unless we tell the xaml where to find the command. So update the ContentPage element


1
2
3
4
5
6
7
&lt;ContentPage
  xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:viewmodel="clr-namespace:MauiApp1.ViewModel"
  x:Class="MauiApp1.MainPage"  
  x:DataType="viewmodel:MainPageViewModel"
&gt;

Press play.

Every time you press the button the text button will change.

Error message “No process is associated with this object.”

May 17th, 2022

If, when starting your web application/service in Visual studio, you get:

—————————
Microsoft Visual Studio
—————————
No process is associated with this object.
—————————
OK
—————————

Check the output, or try starting in debug mode, and a more ´valuable error messag might pop up.

Pseudo random

April 28th, 2017

I have started developing a lib for creating pseudo randomised data. (yes, I know all randomised data on a computer is pseudo randomised, but in my case I want to control the seeding)

The lib, basically, is the ordinary dotnet random class with constructor with some customised constructors to make it easier to add a known seed. It also contains methods for randomising strings with a prefix, a certain length, int, long, decimal, guid, enum and other stuff that is often used.

The seeding is taken from the test method’s name.
This will give the same values for every test run of that method.

Trick of the trade – set enum to not zero

July 5th, 2016

When defining enums set the first of the items to a non-zero value.
This way one knows whether one has forgotten to set the value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
                   
public class Program
{
    private static int SomeNonInitiatedValueFromSomewhere = 0;
   
    public enum MyEnum
    {
        AnItem = 1,
        AnotherItem
    }
   
    public static void Main()
    {
        var myEnum = MyEnum.AnotherItem;
        MyEnum myForgottenEnum = (MyEnum)SomeNonInitiatedValueFromSomewhere;
           
        Console.WriteLine("Now={0}", DateTime.Now.ToString("HH:mm"));
       
        Console.WriteLine("myEnum={0}", myEnum); // This enum is set.
       
        Console.WriteLine("myForgottenEnum={0}", myForgottenEnum); // This enum is not set.
    }
}

from https://dotnetfiddle.net/17tQMB

Dotnet, Sysinternals DebugView, Debug.WriteLine and IIS

September 6th, 2014

I finally managed to write through Debug.WriteLine to Sysinternals DebugView through reading this article. Kudos to the author.

If the original article disappears; here is the recipe in short:

Start Sysinternals Debugview as administrator. Make sure Capture global win32 is checked.
Make sure Visual studio is not attached as debugger because when you run the VS debugger it hogs all information. (In VS you can find the output in the Output window with Show output from Debug.)

Besides Debug.WriteLine also play around with Trace.WriteLine and Console.WriteLine.

Testing internal classes without making them public

May 15th, 2013

…with a trick to make private methods testable too.

When doing automatic tests one often wants to get to the internal classes.

Testing internal stuff

The possibly simplest way is to use InternalsVisbleTo and write

1
[assembly:InternalsVisibleTo("MyTestingProject.With.FullName)]

in the testee’s AssemblyInfo.cs

Or one can write just before the namespace declaration too

1
2
3
4
[assembly:InternalsVisibleTo("MyOtherProjectNameLikeExampleAbove")]
namespace Whatever{
class Hello{
...

<shrugging shoulders>Thats all there is to it.</shrugging>

The namespace is System.Runtime.CompilerServices.

One can decorate InternalsVisibleTo with keys and stuff to harden who gets to the internals but why bother? As long as it is dotnet some reflection can get pass the threshold anyway.

Testing private stuff

Another way I have used is to make a wrapping class “UT_Customer” or method “UT_Create” that 1) wraps the internal class/method, 2) is public and 3) is clearly marked with something conspicuous like “UT?_”. If a drive by programmer sees a method with a weird name and doesn’t bother to read the xml comments and still uses the method and fails; I consider it his fault, not mine. Not that I would use an undocumented method, no never.

1
2
3
4
5
private int AddCustomer(Customer customer){...}

internal int UT_AddCustomer(Customer customer){
return AddCustomer(customer);
}

Moq caveat

There is a caveat where interfaces are not visible for Moq as described here.

The symptom is an error message like

Message: Initialization method Base.UnitTests.Command.CommandHandlerTest thre exception.
Castle.DynamicProxy.Generators.GeneratorException:
Castle.DynamicProxy.Generators.GeneratorException: Type Base.Command.IUndoRedoStack[[Base.Command.ICommand, Base, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] is not public. Can not create proxy for types that are not accessible.

The remedy is to add

1
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]

Update

I see at Metzianou that one can add build variable stuff like $(AssemblyName) like so:


1
&lt;InternalsVisibleTo Include="$(AssemblyName).Tests" /&gt;

Tip when using DebuggerDisplay in Dotnet/Visual studio

March 7th, 2013

When debugging and watching an object one only sees the name of the type in the debugger.

1
MyProjectNamespace.Meeting

The quickest solution is to click the little plus sign or use the keyboard right arrow to show the properties. This is ok to do once or twice but doing this for every comparison is a waste of time at best.

Better then is to use SystemDiagnostics.DebuggerDisplay like so:

1
2
3
[DebuggerDisplay("ID:{ID}, UID:{UID}, Name:{Name}, Type:{this.GetType()}")]
public class Meeting : BaseClass {
...

to get

1
ID:1, UID:234abc, Name:XYZ, Type:MyProjectNamespace.Meeting

The Tip was to use {this.GetType()} in the argument of DebuggerDisplay.

Update

To show count of lists use something in the lines of:

1
[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]

Update update

Since the DebuggerDisplay parameter is written as is into the assembly it might not work between languages. A solution for this is to call a method instead as most lanuguages uses the MyMethod() syntax.

It is also creates less overhead to call a method instead of having the expression in a string according to the MSDN link below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class ExchangeRateDto
{
public int ID { get; set; }

public string Name { get; set; }

#if DEBUG
private string DebuggerDisplay()
{
return
$"ID:{this.ID}, Name:{this.Name}, Type:{this.GetType()}";
}
}
#endif

Update update update

Use nameof. Also skip the this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class ExchangeRateDto
{
public int ID { get; set; }

public string Name { get; set; }

#if DEBUG
private string DebuggerDisplay()
{
return
$"{nameof(ID)}:{ID}, {nameof(Name)}:{Name}, Type:{GetType()}";
}
}
#endif

Update update update update

I have noticed that in Visual Studio 2022 (possibly earlier) one can ctrl-. on the class or record name and Visual studio writes the boilerplate code. The DebuggerDisplay is called GetDebuggerDisplay and only returns this.ToString() unfortunately. So it has to be adapted.

Praise where praise is due: https://blogs.msdn.microsoft.com/jaredpar/2011/03/18/debuggerdisplay-attribute-best-practices/.

There is more documentation at Stack overflow documentation.

Search Term: DebuggerDisplayAttribute

Talking to Neo4j running on OSX from Windows7

July 5th, 2012

This is not a deep diving article but just a brain dump.  Maybe it will help someone.  At least it works on my machine.

I wanted to use Neo4j with dotnet.  So I put Neo4j as a server on the Mac and my regular dotnet stuff on a Win7 machine running through Parallels.

I don’t remember exactly what was needed to get Neo4j up and running but it was easy I recall.  Download.  Extract.  Find the right folder.  Type “neo4j start”. Open a browser.  Type “localhost:7474”.  Create a node.  Check it was created.  Done.
I opted for running Neo4j stand alone to keep my machine tidy – starting the Neo4j server every time I develop is easy.

Since I want to talk to Neo4j from another machine I need to bridge the network and open the firewall on the mac.  It’s just a google away even though the way to open the firewall seems to shifts with every OSX release.  To the better in my case.

A caveat that burned some time for me was that the admin GUI for Neo4j is set to only answer on localhost.  It is considered a good thing since there is no usr/pwd.  That is solved by updating the config and restarting the Neo4j server. Use http://yourmachine:7474 to check this.

On the Windows/Visual studio/Dotnet side I opted for Neo4jclient since it is under present development and open source.  The 2 top hits I found otherwise had their last update set in 2010.  It’s an easy install with Nuget.

Creating nodes from dotnet was easy.  I just followed the getting started.

That’s all I’ve done for now.

List of list and collection classes in dotnet

March 14th, 2012

Which List/Collection to use and where?

What do I choose and what do I have to choose from?

I have found no comprehensive, and good, list so here is a stab at it. Much of it thanks to Gary Short and his video.

Update: There is more, and deeper, information by James Micael Hare.

Update: With Dotnet3 came ReadOnlyObservableCollection. I have not looked into this one.

Update: With Dotnet4.5 three new read only lists are found; IReadOnlyList, IReadOnlyDictionary and IReadOnlyCollection. There is also the Immutable namespace that contains the whole set of basic list variants like Dictionary, List, Queue, Set, Stack, Array, Dictionary, HashSet, SortedDictionary and SortedSet.

Update: At the time of writing we are at Dotnet4.7 and even more lists might have been added. If you know of a such, please comment and I will update this list.
Also: Many of the list types I have annotated “Dotnet 4.5”. This does not mean the type ends with Dotnet4.5 but that I have not investigated the type’s existence later than 4.5.

Update: Now we are at Dotnet 4.8 and have been told it is the last one since Dotnet Core and Dotnet Standard has happened; not to mention UWP and Xamarin. Then there is Mono (non Xamarin variant). I have stopped updating versions as they got stale so fast.

Update: It is now Dotnet 7 and I have lost count of all the list-ish types. There is also the parallelised version of list-ish. Nick Chapsas has 13 fast paced minutes about performance on List<>. Tip: the size of the list affects which is fastest and parallel has effect and Span too, albeit with side effect.

List<T>

http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx
Dotnet 2-4.5

( This chapter has the most information and explanations that won’t be repeated in for the lesser used lists. )

This is the one we “normally” use. If you use it as return you should use IList<T> instead as interfaces gives you more decoupling.

Good: Simple to use. No brainer, especially for short lists. Usable with lambda.
Bad: Adding can be expensive. Removing even more so. (I haven’t checked Insert but it should be expensive too.)
There are some caveats with List<T> though.

method: Add(…)

One is that it allocates space in chunks that increas as the list grows bigger. By your first myList.Add(…) dotnet allocates 4 items. When you add a fifth element it doubles the allocation so 4 new are allocated. Now 8 items are allocated, 5 used and 3 wasted. When you add your 9th, 8 new are allocated.

Like this.
4, 8, 16, 32, 64, … you get the idea of doubling.

Now note that the doubling not only is a waste in space but also ticks. Every time the list is extended a call to Array.Copy(…) is made and memory copying is expensive. I haven’t any good figures but check the Gary Short’s cast linked in this article and wind to 15:30.

When one allocates directly in the constructor like this:

var myList = new List<int>(){1,2,3,4,5};

nothing really changes. Behind the scenes 5 myList.Add(…) are called and you still have 8 items allocated.

A way to mitigate this is to tell the compiler how big list you want:

var myList = new List<int>(5);

Now you get 5 items, allocated once. On the other hand it also changes the allocation scheme to multiples of 5

5, 10, 15, 20, …

which might be exactly what you wanted or not.

The way to do this at constructor time is:

var myList = new List<int>(5){1,2,3,4,5};

If you know you are adding a lot of items avoid looping and instead use .AddRange like this:

myList.AddRange( new int[]{6,7,8,9} );

methods: Remove(…) and RemoveAt(…)

Remove does a linear search for your object. Performance is O(n). RemoveAt just goes to the index and removes the item which gives us O(1). Unless you have veeery long lists both methods are considered fast. But. Remember that Remove(…) does a comparision which comes in three flavours IEquatable<T>, Equals and bitwise. Wind to 18:00 in the linked cast.

method: Sort

Sorting is done with Quicksort. Unless you have special cases like an almost ordered list or – even worse – an ordered list, this is a fast sorting algorithm. Performance is O(n log n) in best case and O( n^2) in worst case.

If you have an ordered list, which we often have, you could get some benefit of randomising the list first. Or the obvious: check if the list is ordered before sorting it. Or use another list or collection; which this article is about…

LinkedList<T>

http://msdn.microsoft.com/en-us/library/he2s3bh7.aspx
Dotnet 2-4.5

This is a double linked list.

Good: Fast for Add, Remove and Insert.
Bad: Searching is slower.

Since Add, Remove and Insert only manipulates the item at hand and the items just before and after the performance is O(1).

Searching and going to a certain index means traversing the list and hence performance is O(n).

Dictionary<TKey, TValue>

http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
Dotnet 2-4.7

Good: Fast for searching. Implementing your own key type can be a problem.
Bad: Only one key.

The dictionary is a key-value store. This is considered fast since the comparision between two items depend on a key and not on the whole item.
Here the caveat is on the comparision on the key. The comparision is dependant on the hash key which, if expensive, makes this list less performant.

A simple key like a string (not too long) or a number is fast when the key is evenly distributed. What this means is that lots of keys around 100 and a few around 10000 makes worse performance than if the keys are spread 100, 200, 300, 400 etc. Not a tool good example of me and that is why web searching is your friend.

There is a helper method for quickly creating a dictionary from a GroupBy. See here for example.

Caveat: if you have an object as the key comparision is done through IEquatable.Equals or by overriding Equals and when you do (which you should do once in a while just for the fun of it) you have to override GetHashCode too. And following this you must now grokk both hashing of an object and the hashing theories. Personal recommendation: don’t write the code in a few minutes just because you can; invest a couple of hours in it. It will pay off in the long run.
Also note that hashes are only theoretically unique. This means you can get two hits for the same hash.
Then note that if you write a class where Equals is not overriden dotnet will compare the reference; but if you have an anonymous class dotnet will do a shallow(?) comparison.

Lookup<TKey, TValue>

http://msdn.microsoft.com/en-us/library/bb460184.aspx
Dotnet 3.5-4.6

Good: has several items for each key. Fast searching through the key.
Bad: has several items for each key.

This is a Dictionary<TKey,TValue> variant with the addition that it can take several items for the same key.
Note: For a reason unkown to man the interface is totally different though; it uses an extension method ToLookup which takes  lambda as parameters. I guess there is some good rationale behind this since it the guys behind this are smart.

One creates a Lookup<TKey,TValue> by calling ToLookup on an IEnumerable<T> and the syntax is quite nice.

Note that this list is immutable so nothing can be added to or deleted from the Lookup when it is created.

SortedList<TKey, TValue>

http://msdn.microsoft.com/en-us/library/ms132319.aspx
Dotnet 2-4.5
There is a generic SortedList too.

Good: Sorted. Fast retrieval [O( log n )].

Uses less memory than SortedDictionary<T>.
If you add lots of data at once, use SortedList<T> instead of SortedSet<T> or SortedDictionary<T>.

SortedSet<T>

http://msdn.microsoft.com/en-us/library/dd412070.aspx
Dotnet 4-4.5

Good: Sorted. Fast retrieval [O( log n )].
See more at http://msdn.microsoft.com/en-us/vstudio/ee906600

SortedDictionary<TKey, TValue>

http://msdn.microsoft.com/en-us/library/f7fta44c.aspx
Dotnet 2-4.5
There is a generic version too.

Good: Sorted. Fast retrieval [O( log n )]. Faster insert and remove than SortedList<T>.

ConcurrentBag<T>

http://msdn.microsoft.com/en-us/library/dd381779.aspx
Dotnet4-4.5

Used for concurrency. They don’t solve the problem of concurrency conflicts but mitigates them. Every fetch of add should be tried. The add method is called TryAdd and return true/false depending on if you succeeded or not; the same with TryTake. Yes, this means an if(…) for every such call and corresponding handling. That is one of the reasons concurrency is hard. And fun.

Check out int.TryParse for an easier-to-test method with the same functionality.

ConcurrentDictionary<T>

http://msdn.microsoft.com/en-us/library/dd381779.aspx
Dotnet 4-4.5

Used for concurrency. They don’t solve the problem of concurrency conflicts but mitigates them. Every fetch of add should be tried. The add method is called TryAdd and return true/false depending on if you succeeded or not. Yes, this means an if(…) for every such call and corresponding handling. That is one of the reasons concurrency is hard. And fun.

ConcurrentQueue<T>

http://msdn.microsoft.com/en-us/library/dd267265.aspx
Dotnet 4-4.5

See ConcurrentDictionary.

ConcurrentStack<T>

http://msdn.microsoft.com/en-us/library/dd267331.aspx
Dotnet 4-4.5

See ConcurrentDictionary.

OrderablePartioner<T>

http://msdn.microsoft.com/en-us/library/dd394988.aspx
Dotnet 4-4.5

See ConcurrentDictionary.

Represents a particular manner of splitting an orderable data source into multiple partitions. Not only does it work particular but is also is named totally different. I predict this list will almost never be used since noone finds it.

BlockingCollection<T>

http://msdn.microsoft.com/en-us/library/dd267312.aspx
Dotnet 4-4.5

See ConcurrentDictionary.

Now this collection is slightly different regarding add/remove since it can block and give you true safety. But also deadlocks. If you don’t know what a deadlock is, and don’t fieel like studying this, just go and ask a SQL guy for transactions and deadlocks and he’ll have about the same problem and answers. If you understand what s/he says you’ll understand BlockingCollection.Add too.

One can set a timeout. Ask the SQL guy if you wonder what that sentence meant.

ObservableCollection<T>

http://msdn.microsoft.com/en-us/library/ms668604.aspx
Dotnet 3-4.5

Used typically for MVVM in WPF or Silverlight.

Good: can tell others about its state changes.

If you have a collection and want to watch over it to see if it changes – then this collection is for you. Start a WPF project if you want to play around and test it.

Due to a reason known to only a few this collection is defined in the WindowsBase assembly.

Uses List<T> internally so anything that applies to List<T> applies to ObservableCollection too.

ListDictionary

http://msdn.microsoft.com/en-us/library/system.collections.specialized.listdictionary.aspx
Dotnet 1.1-4.5

A Dictionary implementing IDictionary as a key-value pair linked list. Check Dictionary for what that means.

This list is suitable for lists with fewer than 10 items and even though you probably can retrieve the items in the same order every time, don’t depend on it since Microsoft has specified that the order might change.

It is generic which means type casting is up to you.

OrderedDictionary

http://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary.aspx
Dotnet 2-4.5

Uses key-value pairs and have them ordered. Duh.

It is generic which means type casting is up to you.

HybridDictionary

http://msdn.microsoft.com/en-us/library/system.collections.specialized.hybriddictionary.aspx
Dotnet 1.1-4.5

Changes to a ListDictionary if the items are few and a Hashtable if they are many. “Few” and “many” has a breakpoint around 10.

One can change if comparision is case sensitive or not.

The key cannot be null.

StringCollection

http://msdn.microsoft.com/en-us/library/system.collections.specialized.stringcollection.aspx
Dotnet 1.1-4.5

Optimised for string lists.

One can store null, allows duplicates, case sensitive comparision; just the same as List<string> but supposedly faster. If someone had some performance figures or reverse engineered code we might know.

StringDictionary

http://msdn.microsoft.com/en-us/library/system.collections.specialized.stringdictionary.aspx
Dotnet 1.1-4.5

Implemented as hash table. Case insensitive comparision. I haven’t checked but I suppose it does ToLower or ToUpper on the keys before storing them. At least that is what I should have done.

StringDictionary is generic and I suppose it exists solely because generics didn’t exist in Dotnet 1.1 and instead of everyone writing their own StringDictionary with their own casts Microsoft built it for everyone (and for themselves of course).

SortedList

http://msdn.microsoft.com/en-us/library/system.collections.sortedlist.aspx
Dotnet 1.1-4.5

Generic list. Do your own type casting.

SortedDictionary

http://msdn.microsoft.com/en-us/library/f7fta44c(v=vs.80).aspx
Dotnet 2-4.5

Generic version. Do your own type casting. And debug your own bugs.

Dictionary

http://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.80).aspx
Dotnet 2-4.5

Is this really correct? Didn’t we have Dictionary in dotnet 1 and 1.1? I vividly remember writing my own version (see StringDictionary) for every type I had.
Which brings me to that it isn’t very difficult inheriting from Dictionary and overriding the right methods. There is (at list was back in last century) cookbooks for this on the web. Today I just use List<T> and am happy with it.

HashSet<T>

http://msdn.microsoft.com/en-us/library/bb353005
Dotnet 3.5-4.5

I have not experimented with this one.

IList<T>

IList is the interface behind List<T>. Use it when you can.
Especially when returning a List, return IList instead to get more decoupling.  Especially especially when writing a framework.

http://stackoverflow.com/questions/400135/c-sharp-listt-or-ilistt

ArrayList

https://docs.microsoft.com/en-us/dotnet/api/system.collections.arraylist

HashTable

https://docs.microsoft.com/en-us/dotnet/api/system.collections.hashtable

IReadOnlyList<T>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlylist-1

IReadOnlyDictionary<TKey, TValue>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlydictionary-2

IReadOnlyCollection<T>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.ireadonlycollection-1

ReadOnlyObservableCollection<T>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.readonlyobservablecollection-1

Queue

https://docs.microsoft.com/en-us/dotnet/api/system.collections.queue

Queue<T>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1

ISet

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.iset-1

Stack

https://docs.microsoft.com/en-us/dotnet/api/system.collections.stack

Stack<T>

https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.stack-1

Array

This class does not reside in any collection namespace but is still considered a collection since it implements IList. But at the same time it is fixed in size.

If I understand the dox correctly it is the base class for anything Collection but we, as external developers, should not use it; it is solely for the langauge and the compiler people.

It contains a IsFixedSize property which always is True.

https://docs.microsoft.com/en-us/dotnet/api/system.array

Performance tips

These tips come from Gary Short unless noted.

Boxing/unboxing takes time so if you have value types (int, char etc) (not string that even though it behaves like a value type isn’t one) use generic collections instead.
My comment: casting can fail runtime but un/boxing through, say, List<T> never does so 99 of 100 times I prefer the performance penalty. I also have no figures on the costs. Someone?

All lists, except LinkedList has O(1) for adding an item unless it results in growing when we get O(n). LinkedList never grows in chunks and always have O(1). Se more about growing under List<T>.

List<T> sorts slower when the list is almost sorted and slowest when it is already sorted. This is not schtoopidity but a drawback of the quicksort algorithm.

SortedList<T> uses less memory than SortedDictionary<T> but the latter has faster add/remove.

Also

The cast of Gary Short at Öredev is found here.
More info on collections is found here:

Function within a method in C# / csharp / dotnet

March 5th, 2012

I have since the birth of dotnet missed the possibility to have a function inside a function like one can in Pascal.

With lambda, and possibly Dotnet4(?) it is possible.  Below is a rather stupid example.

1
2
3
4
5
6
7
8
internal int AddMaxWierd( int x, int y )
{
Func Max = delegate( int a ){
return Math.Min( a, 10 );
};

return Max(x) + Max(y);
}

If the inner method doesn’t have a return value, use “Action” instead of “Func”.
See how there is only one Manipulate method in the class, the other Manipulate method is hidden within the method.

1
2
3
4
5
6
7
8
9
10
11
12
internal void Manipulate( CustomerList Customer customers )
{
Action&lt;Customer&gt; Manipulate = delegate( Customer customer )
{
// do stuff...
};

foreach( var customer in customers ){
Manipulate( customer );
}

}

 

Update:

In C#7 it can be done. https://github.com/dotnet/roslyn/issues/6505