C # Кастинг словаря - PullRequest
       13

C # Кастинг словаря

3 голосов
/ 23 февраля 2011

У меня есть эта функция:

void WriteMap(object value)  
{  
    IDictionary<string, object> vv = (IDictionary<string, object>)value;  
    foreach (KeyValuePair<string, object> obj in vv)  
    {  
        (write key)  
        (write value)  
    }  
}  

Это работает, если значение действительно имеет тип IDictionary<string, object>, но это может быть что-то вроде:
IDictionary<string, int> IDictionary<string, MyClass> IDictionary<string, string[]> и т.д.

Приведение вызывает исключение во время выполнения. Функция не изменяет контейнер, она только печатает ключи и значения. Любые идеи о том, как я могу сделать эту работу? Любая помощь будет принята с благодарностью.

Спасибо!

Ответы [ 4 ]

3 голосов
/ 23 февраля 2011

Добавьте параметр универсального типа в ваш метод, соответствующий типу значений в вашем словаре:

void WriteMap<T>(IDictionary<string, T> dict)
{
    foreach (KeyValuePair<string, T> in dict)
    {
        // write key
        // write value
    }
}

Преимущество этого состоит в устранении приведения.Если вам по какой-то причине необходимо передать словарь как объект, просто приведите его к IDictionary.

1 голос
/ 23 февраля 2011

Прежде всего, почему ваша функция получает object в качестве параметра, а затем пытается преобразовать его в IDictionary?Это очень плохая практика, потому что вызывающий код не знает, что значение должно быть приведено .

Если вы хотите, чтобы функция работала только с IDictionary (без поздней привязки)магия и прочее), изложите это явно.Это, вероятно, место, где вы врезались в стену: вам нужно, чтобы он принял любой IDictionary, верно?Возможно, именно поэтому вы пытались использовать object и приведение типов.

Вместо этого вы должны объявить свой метод универсальным:

void WriteMap<TKey, TValue>(IDictionary<TKey, TValue> dict)  
{  
    foreach (var kv in dict) // kv is KeyValuePair<TKey, TValue>
    {  
        // (write key)  
        // (write value)  
    }  
}  

Вы можете даже применить некоторые условияна TKey и TValue, если хотите, см. where ограничения типа .

В вашем случае кажется, что ключ всегда равен string, поэтому вы можете ввестиуниверсальный параметр только для значения:

void WriteMap<TValue>(IDictionary<string, TValue> dict)  
{  
    foreach (var kv in dict) // kv is KeyValuePair<string, TValue>
    {  
        // (write key)  
        // (write value)  
    }  
}  

Одним из недостатков этого метода является то, что компилятор должен иметь возможность выводить тип TValue во время компиляции.Если оно неизвестно или типы значений могут отличаться, может иметь смысл использовать неуниверсальный IDictionary вместо:

void WriteMap(IDictionary dict)  
{  
    foreach (var kv in dict) // kv is DictionaryEntry
    {  
        // (write key)  
        // (write value)  
    }  
}  

Обратите внимание, что в этом случае ключ не ограничен string.

1 голос
/ 23 февраля 2011

Приведите его к неуниверсальному IDictionary:

IDictionary vv = (IDictionary)value;  
foreach (var key in vv.Keys)  
{  
    var value = vv[key];
}  
0 голосов
/ 23 февраля 2011

Если вы просто хотите распечатать значения, вы можете использовать неуниверсальный интерфейс IDictionary :

void WriteMap(object value)  
{  
    IDictionary vv = (IDictionary)value;  
    foreach (DictionaryEntry de in vv)  
    {  
        object key = de.Key;
        object value = de.Value;
        (write key)  
        (write value)  
    }  
}  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...