2016-07-01 14 views
-1

Я пытаюсь создать диспетчер сцены или штата, который хранит словарь для каждого состояния в качестве способа загрузки или изменения состояния программы (например, состояние главного меню и Состояние игры). У меня есть куча производных классов базового класса State, которые имеют переменные, которые не включены в базовый класс State. Могу ли я безопасно хранить их в этом словаре? Будет ли у меня потеря данных? Если это не сработает, каковы альтернативные методы для достижения моей цели?Хранение производных классов в базовом классе Словарь

ответ

1

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

public class Base 
{ 
    public string Name 
    { 
     get; 
     set; 
    } 

    public override string ToString() 
    { 
     return Name; 
    } 
} 

и производный класс, как:

public class Derived : Base 
{ 
    public string Description 
    { 
     get; 
     set; 
    } 

    public override string ToString() 
    { 
     return base.ToString() + " - " + Description; 
    } 
} 

Затем вы можете создать настройку, как это:

Base baseObject = new Base{ Name = "Base"}; 
Derived derivedObject = new Derived { Name = "Derived", Description = "Description" }; 

Dictionary<int, Base> dictionary = new Dictionary<int, Base>(); 
dictionary.Add(1, baseObject); 
dictionary.Add(2, derivedObject); 

Теперь вы можете запустить небольшой тест, чтобы увидеть, если какая-либо информация будет потеряна:

foreach (Base value in dictionary.Values) 
{ 
    Console.WriteLine(value.ToString()); 
} 

Как вы можете видеть, вызывается не только правильный переопределенный ToString(), но также он имеет правильное значение для свойства Description. Так что нет, вы ничего не «теряете». Но до тех пор, пока это тип base, вы можете получить доступ только к объектам base.

КПП. Вы также можете проверить, если значение действительно is определенный производный тип:

foreach (Base value in dictionary.Values) 
{ 
    if (value is Derived) 
    { 
     Console.WriteLine("{0} is Derived", value.Name); 
     // trying to access value.Description at this point 
     // would cause a compiler error "Cannot resolve symbol". 
    } 
    else 
    { 
     Console.WriteLine("{0} is not Derived", value.Name); 
    } 
} 

И as и чек на нуль, вы можете «безопасно» (т.е. без исключения, вызванного прямым литьем, например) получить значение в «полный» производственный тип, где снова можно получить доступ ко всем дополнительным свойствам:

foreach (Base value in dictionary.Values) 
{ 
    Derived derived = value as Derived; 
    if (derived != null) 
    { 
     Console.WriteLine("{0} is Derived and has Description: {1}", 
          derived.Name, derived.Description); 
     // now that derived actually is of type Derived, 
     // accessing derived.Description is perfectly fine. 
    } 
}