Goal: get a value from a dictionary. Said value has a dictionary as a key.
What I'm doing: I'm creating a second dictionary that has the exact same values as the key whose value I'm trying to get. Using TryGetValue
Result: Expecting a value but getting null;
Context: I'm trying to make a crafting functionality in Unity. This is what the class for a crafting ingredient looks like (ICombinable looks the exact same right now):
public class Ingredient : ICombinable
{
public string Name { get; set; }
public string Description { get; set; }
public Effect Effect { get; set; }
}
In practice I want a user to be able to drag objects of type ICombinable onto the UI(not implemented) and press a button to combine them into a new item. For example, 2 herbs and 1 glass of water return a healing potion(a new item).
Behind the surface, I will store the dragged/selected objects in a Dictionary<ICombinable, int>
where int is the amount per ICombinable
.
In another class, I am storing another Dictionary which is going to hold all the recipes.
public class Combiner
{
private Dictionary<Dictionary<ICombinable, int>, ICraftable> _recipebook;
public Combiner()
{
_recipebook = new Dictionary<Dictionary<ICombinable, int>, ICraftable>(); // <Recipe, Item it unlocks>
}
public void AddRecipe(Dictionary<ICombinable, int> recipe, ICraftable item) => _recipebook.Add(recipe, item);
public ICraftable Craft(Dictionary<ICombinable, int> ingredientsAndAmount) =>
_recipebook.TryGetValue(ingredientsAndAmount, out var item) == false ? null : item;
//FirstOrDefault(x => x.Key.RequiredComponents.Equals(givenIngredients)).Value;
}
The key of _recipebook is the actual recipe comprised of ingredients and their amounts. ICraftable is the object/item that corresponds with that recipe. In the example I gave earlier ICraftable would be the healing potion and the 2 sticks and the glass of water would each be an entry in the Dictionary that is the key of that value.
And lastly, the Craft method takes a dictionary(in other words a list of ingredients and their amounts) and I want it to check in the _recipebook which item corresponds with the given dictionary. If the combination of ingredients is valid it should return an item, otherwise null.
How I am testing this functionality: I just started the project so I wanted to start with unit testing. Here is the setup:
[Test]
public void combiner_should_return_healing_potion()
{
// Use the Assert class to test conditions
var combiner = new Combiner();
var item = new Item
{
Name = "Healing Potion",
Unlocked = false
};
combiner.AddRecipe(new Dictionary<ICombinable, int>
{
{new Ingredient {Name = "Herb", Description = "Has healing properties", Effect = Effect.Heal}, 3},
{new Ingredient {Name = "Water", Description = "Spring water", Effect = default}, 1},
{new Ingredient {Name = "Sugar", Description = "Sweetens", Effect = default}, 2}
},
item);
var actualItem = combiner.Craft(new Dictionary<ICombinable, int>
{
{new Ingredient { Name = "Herb", Description = "Has healing properties", Effect = Effect.Heal} , 3},
{new Ingredient {Name = "Water", Description = "Spring water", Effect = default}, 1},
{new Ingredient {Name = "Sugar", Description = "Sweetens", Effect = default}, 2}
});
Assert.That(actualItem, Is.EqualTo(item));
}
Result:
combiner_should_return_healing_potion (0.023s)
---
Expected: <Models.Item>
But was: null
---
I am creating an item called healing potion and a dictionary that should be its recipe. I add these to the recipe book. After that, I am creating a second dictionary to "simulate" a user's input. The dictionary has the exact same content as the one I am adding to the recipe book with Add
recipe(). How come that TryGetValue
does not see these two dictionaries as equal?
What can I do to get it working?