Можно ли передать универсальный словарь в качестве параметра методу, ожидающему IDictionary - PullRequest
3 голосов
/ 29 октября 2009

AssemblyInstaller.Install ожидает System.Collections.IDictionary.

Имею ли я право на «аллергию» на использование неуниверсальных коллекций, таких как Hashtable, или я должен преодолеть себя?!

, например

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);
        }
    }
}

Кроме того, компилятор не имеет проблем с этим удалением:

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

Но случится ли что-нибудь плохое во время выполнения, если кто-то использует что-то кроме строк в качестве ключей?


Обновление [Отражатель для спасения]

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

Подтверждая слова Джона, словарь реализует IDictionary следующим образом:

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

... поэтому при проверке ключа будет выдано исключение, если тип ключа не совпадает с тем, который использовался при объявлении конкретной специализации универсального словаря (и аналогично для типа значения):

private static void VerifyKey(object key)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    if (!(key is TKey))
    {
        ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
    }
}

Ответы [ 2 ]

4 голосов
/ 29 октября 2009

Поскольку установщик принимает объект IDictionary, он должен иметь возможность работать с любым словарем, переданным ему. По крайней мере, это мое мнение ... если я возьму интерфейс, я должен уметь справляться с любой его реализацией.

Кроме того, я бы посоветовал вам просто попробовать.

2 голосов
/ 29 октября 2009

Это работает, потому что Dictionary<TKey, TValue> реализует IDictionary - но он действительно потерпит неудачу во время выполнения, если кто-то вызовет IDictionary.Add(object, object) с не строковый ключ - вы получите ArgumentException.

Обратите внимание, что сам интерфейс IDictionary<TKey, TValue> не расширяется IDictionary - просто реализация Dictionary<TKey, TValue> 1018 * также реализует IDictionary.

...