Есть ли способ избежать приведения при работе с Hashtables в C #? - PullRequest
0 голосов
/ 29 июля 2011

Мне интересно, есть ли способ перезаписать класс Hashtable (или Dictionary), чтобы он автоматически выполнял операции упаковки / распаковки объектов. Другими словами:

myHashtable["value1"] = "this_is_string";
myHashtable["value2"] = 123;

string a = myHashtable["value1"];
int b = myHashtable["value2"];
// errors as expected, since i need to cast it to specific type from object

И, очевидно, C # не допускает перезаписи public T этого [object key] оператора с различными типами, так как я пытался сделать что-то вроде этого:

public int this[object key] { get { return (base[key] as int); } set {} } // etc
public string this[object key] { get { return (base[key] as string); } set {} } // etc
// error

Любые идеи или советы, как проще всего (если есть) избегать приведения при использовании ассоциативных массивов в C # (нет необходимости строго использовать Hashtable)? И если нет способа сделать это, я был бы признателен, если бы кто-то более знающий, чем я, объяснил, почему это так и каковы основные принципы этого.

Спасибо.

Изменить: Мне это нужно, потому что я создаю собственный класс настроек. Настройки могут иметь разные типы значений, например, скажем, «HowManyItemsToDisplay» будет иметь некоторое целочисленное значение, а «NameOfSomeControl» будет строкой. Поэтому было бы неплохо избегать кастинга при написании чего-то вроде:

myControl.Text = MySettings["SomeTextValue"];

или

while (MySettings["SomeIntValue"] > 0) { .. }

Ответы [ 5 ]

5 голосов
/ 29 июля 2011

Словари обеспечивают безопасность типов, вы не можете просто бросить в них что-нибудь.HashTables не являются общими и используют объекты, поэтому вы вынуждены включить / распаковать.Краткий ответ: нет , вы не можете перезаписать эту функцию для HashTable.Ответ заключается в том, чтобы использовать дженерики, если можете.

Если вы не ориентируетесь на более старую среду .net, я бы сказал, придерживайтесь родового словаря.

2 голосов
/ 29 июля 2011

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

myHashTable.GetAs<string>("value1");
myHashTable.GetAs<int>("value2");

public static T GetAs<T>( this Hashtable ht, object key )
{
    return (T)ht[key];
}

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

И чтобы быть совершенно ясным, кастинг и бокс все еще там, просто скрыты от глаз.

Дополнительный ответ для редактирования:

Если вы можете использовать C # 4, я думаю, что вы можете получить желаемое синтаксически с помощью Dictionary<object,dynamic>. Конечно, если вы можете сделать это, вы можете просто сделать объект настроек динамическим и использовать вместо этого синтаксис mySettings.Value1.

0 голосов
/ 29 июля 2011

Я думаю, если вы знаете, что Типы предопределены, всегда полезно использовать Универсальную версию Коллекции, такую ​​как:

Список вместо ArrayList, Array Словарь вместо HashTable в свою очередь KeyValuePair вместо объекта

Универсальная версия Stack & Queue и т. Д.

Это важно, несмотря на то, что во многих устаревших кодах, даже внутри Microsoft BCL, используются неуниверсальные коллекции, но для новых разработок дженерики всегда являются предпочтительным выбором.

Даже вы можете использовать Generic Variance, представленный в .NET 4.0 , если вам нужно.

0 голосов
/ 29 июля 2011

C # строго типизирован (хорошо, они ослабляют это, но в своей основе ...)

Вы обычно используете словарь, определяющий тип ключа и значение

Вынужен словарь, в котором значение может быть любого типа, и при этом получить значение безопасным для типа способом.Для меня это означает, что вы пытаетесь запрограммировать C #, как если бы это был язык со слабой типизацией, используя хеш вместо создания класса для хранения коллекции связанных значений.

В идиоматическом C # вы редко имеетепричина хранить разные типы значений в одном словаре.

0 голосов
/ 29 июля 2011

вы можете динамически разыгрывать при помощи object.GetType ()

...