Использование словаря <строка, объект> в качестве словаря <строка, словарь <строка, строка >> - PullRequest
3 голосов
/ 08 февраля 2012

в C # Мне нужно хранить данные в объекте словаря, выглядит так:

Dictionary<string, Dictionary<string, string>> MyDict = 
    new Dictionary<string, Dictionary<string, string>>();

Теперь я понял, что в некоторых случаях мне понадобятся некоторые другие (не словарные) данные в качестве значения основного изречения.

Есть ли какая-то проблема или ограничение, если я просто приведу пример главного диктата. как:

Dictionary<string, object> MyDict = new Dictionary<string, object>();

в поле объекта я могу поместить строку, словарь, что угодно ..

Спасибо заранее, С уважением, Стивен

Ответы [ 7 ]

5 голосов
/ 08 февраля 2012

Да, ваш словарь больше не будет строго набираться - при первом подходе вы можете сделать что-то вроде:

string value = myDict["foo"]["bar"];

Во втором подходе это больше невозможно, поскольку вы должны разыграть первого:

string value = ((Dictionary<string,string>)myDict["foo"])["bar"];

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

Edit:

Если вы просто хотите обработать null значения, вы можете просто сделать что-то вроде:

string value = myDict["foo"] != null ? myDict["foo"]["bar"] : null;

Или завернутый в метод расширения:

public static T GetValue<T>(this Dictionary<T, Dictionary<T,T>> dict, 
                            T key, T subKey) where T: class
{
    T value = dict[key] != null ? dict[key][subKey] : null;
    return value;
}

string value = myDict.GetValue("foo", "bar");
4 голосов
/ 08 февраля 2012

Вы можете сделать это.После извлечения данных из основного словаря вам придется преобразовать результат в соответствующий тип:

object obj;
If(mainDict.TryGetValue("key", out obj)) {
    var dict = obj as Dictionary<string, string>>;
    if (dict != null) {
        // work with dict
    } else {
        var value = obj as MyOtherType;
        ....
    }
}

Но обратите внимание, что это небезопасно;т.е. компилятор может только частично проверить правильность вашего кода относительно значений типа object.


В качестве альтернативы вы можете попробовать более объектно-ориентированное решение

public abstract class MyBaseClass 
{
    public abstract void DoSomething();
}

public class MyDictClass : MyBaseClass
{
    public readonly Dictionary<string, string> Dict = new Dictionary<string, string>();

    public override void DoSomething()
    {
        // So something with Dict
    }
}

public class MyTextClass : MyBaseClass
{
    public string Text { get; set; }

    public override void DoSomething()
    {
        // So something with Text
    }
}

Затем объявите ваш основной словарь с

var mainDict = new Dictionary<string, MyBaseClass>();

mainDict.Add("x", new MyDictClass());
mainDict.Add("y", new MyTextClass());

...

MyBaseClass result = mainDict[key];
result.DoSomething(); // Works for dict and text!
1 голос
/ 08 февраля 2012

Используя объект в качестве значения в словаре, вы подвергаетесь некоторому риску и осложнениям:

  • Отсутствие безопасности типа (в качестве значения можно указать все)
  • Вы должны были бы привести к определенному типу, вероятно, основываясь на значении

Вы, вероятно, должны переосмыслить свой дизайн. Но если вам действительно нужна гибкость, вы можете создать новый тип, который будет работать как тип значения. Что-то вроде:

class MySpecialType
{
    public Dictionary<string, string> MyStringDictionary { get; set; }
    public string MyStringVal {get; set;}

    public Type ActiveType { get; set; } // property would specify the current type
    // ...

Ваше основное словарное объявление будет выглядеть примерно так:

Dictionary<string, MySpecialType> MyDict = new Dictionary<string, MySpecialType>();

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

1 голос
/ 08 февраля 2012

Вы потеряете сильные типы и все их преимущества.

Не можете ли вы создать новый класс со свойством Dictionary и добавить к нему другие данные:

public class CallItWhatYouLike
{
  public Dictionary<string, string> Dictionary {get; set;}
  public int AnotherProperty {get; set;}
  ...
}

var MyDict = new Dictionary<string, CallItWhatYouLike>();
0 голосов
/ 08 февраля 2012

Вы будете платить штраф за производительность, когда вы распаковываете System.Object, но кроме этого нет проблем с вашим подходом, кроме чрезмерного приведения для индексаторов ( из-за слабой типизации ).

Вы можете использовать System.Tuple , если вы используете .NET 4.

0 голосов
/ 08 февраля 2012

Ваш код будет менее безопасным, и вам понадобятся проверки типов во время выполнения и приведение типов, но в противном случае вы можете использовать object в качестве типа значения словаря и хранить там любые типы.

0 голосов
/ 08 февраля 2012

Нет, проблем нет. Если вам нужно ввести значение как Dictionary<string, string>, просто приведите его, и вы решите это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...