Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it OK to pass a generic Dictionary as a param to a method expecting IDictionary

AssemblyInstaller.Install expects a System.Collections.IDictionary.

Am I right to be 'allergic' to using non-generic collections such as Hashtable or should I get over myself?!

e.g.

using System.Collections.Generic;
using System.Configuration.Install;
using System.Reflection;
using AssemblyWithInstaller;

namespace InstallerDemo
{
    class InstallerDemo
    {
        static void Main(string[] args)
        {
            var savedState = new Dictionary<object, object>();
            // i.e. as opposed to something that implements IDictionary:
            //var savedState = new System.Collections.Hashtable()
            var assembly = Assembly.GetAssembly(typeof (MyInstaller));
            var ai = new AssemblyInstaller(assembly, new[] {"/LogFile=install.log"});
            ai.Install(savedState);
            ai.Commit(savedState);
        }
    }
}

Additionally the compiler has no issue with this decalration:

var savedState = new Dictionary<string, object>();

But will anything bad happen at runtime if someone uses something other than strings as keys?


Update [Reflector to the rescue]

var savedState = new Dictionary<string, object>();

Confirming what Jon says, Dictionary implements IDictionary as follows:

void IDictionary.Add(object key, object value)
{
    Dictionary<TKey, TValue>.VerifyKey(key);
    Dictionary<TKey, TValue>.VerifyValueType(value);
    this.Add((TKey) key, (TValue) value);
}

...so in verifying the key it will throw an exception when the type of the key doesn't match that used when declaring the particular specialization of the generic Dictionary (and likewise for the type of the value):

private static void VerifyKey(object key)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    if (!(key is TKey))
    {
        ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
    }
}
like image 583
rohancragg Avatar asked Nov 25 '25 01:11

rohancragg


2 Answers

Since the Installer is accepting an IDictionary-Object, it should be able to deal with any Dictionary passed to him. At least that's my opinion...if I take an Interface, I need to be able the handle any implementation of it.

Also, I'd suggest that you just try it.

like image 143
Bobby Avatar answered Nov 27 '25 13:11

Bobby


This works because Dictionary<TKey, TValue> implements IDictionary - but it will indeed fail at execution time if someone calls IDictionary.Add(object, object) with a non-string key - you'll get an ArgumentException.

Note that the IDictionary<TKey, TValue> interface itself doesn't extend IDictionary - it's just that the Dictionary<TKey, TValue> implementation also implements IDictionary.

like image 34
Jon Skeet Avatar answered Nov 27 '25 13:11

Jon Skeet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!