-2

Hi I have a struct and dictionary as below and I'm trying to add it as a custom value like

public struct data_inv
{
    //protected static int p;
    public float inventory;
    public  float supply;
    public  float demand;
};

public static IDictionary<int, data_inv> inv_stored = new Dictionary<int, data_inv>();

and I have tried to add value to dictionary but when I try to add a value like inv_stored[1].demand = 4; its gives System.Collections.Generic.KeyNotFoundException: 'The given key was not present in the Dictionary.' exception. I'm new to coding, could any explain what im doing wrong

Specterhy
  • 11
  • 4
  • Not sure where you get the error you're getting, I'm getting a [very different error](https://dotnetfiddle.net/ueYPJ1), which can be explained by https://stackoverflow.com/questions/18126289/cannot-modify-the-return-value-because-it-is-not-a-variable – gunr2171 Oct 16 '22 at 05:52
  • This has nothing to do with the value in the dictionary being a struct - it has everything to do with fetching `inv_stored[1]` when the key 1 isn't in the dictionary. – Jon Skeet Oct 16 '22 at 06:53

3 Answers3

1

If you want to use a struct instead of a class, write this instead of inv_stored[1].demand = 4 (updated based on comments):

public struct data_inv
{
    public float Inventory;
    public float Supply;
    public float Demand;
    
    public data_inv(int demand)
    {
        Inventory = 0;
        Supply = 0;
        Demand = demand;
    }
};

// ....
    IDictionary<int, data_inv> inv_stored = new Dictionary<int, data_inv>();

    data_inv myData = new data_inv(4);
    inv_stored.Add(1, myData);

This is a way to add keyValue to a Dictionary.

TheMah
  • 378
  • 5
  • 19
  • Thank you for the answer, but when i tried this, at inv_stored.Add(1, myData); is giving Error CS0165 Use of unassigned local variable 'myData' – Specterhy Oct 16 '22 at 06:25
  • @Specterhy You must always assign _all_ the fields of a struct (or just use `new`). – Luaan Oct 16 '22 at 06:26
  • @Specterhy See my updated answer. You can use a `constructor` to assign initial values to the `struct`. – TheMah Oct 16 '22 at 06:35
0

data_inv shouldn't be a struct. It's mutable, and structs shouldn't be mutable, it's not representing a single value. You should make it a class instead.

public class data_inv
{
    //protected static int p;
    public float inventory;
    public  float supply;
    public  float demand;

};

Implementation:

// Add new item into dictionary
inv_stored.Add(1, new data_inv()
{
    inventory = 20,
    supply = 10,
    demand = 5
});

Console.WriteLine(inv_stored[1].demand); // 5

inv_stored[1].demand = 4;
Console.WriteLine(inv_stored[1].demand); // 4

Edit:
Print all elements each in one line:

foreach (var kvp in inv_stored)
{
    Console.Write("bucket:{0} ", kvp.Key);
    Console.Write("inventory:{0}, ", kvp.Value.inventory);
    Console.Write("supply:{0}, ", kvp.Value.supply);
    Console.WriteLine("demand:{0}", kvp.Value.demand);
}

Example output:

bucket:1 inventory:20, supply:10, demand:4
bucket:2 inventory:16, supply:9, demand:7

Print all elements into a table format:

var buckets = inv_stored.Keys;
var inventory = inv_stored.Values.Select(x => x.inventory);
var supply = inv_stored.Values.Select(x => x.supply);
var demand = inv_stored.Values.Select(x => x.demand);

Console.WriteLine("buckets:\t{0}", string.Join("\t", buckets));
Console.WriteLine("inventory:\t{0}", string.Join("\t", inventory));
Console.WriteLine("supply: \t{0}", string.Join("\t", supply));
Console.WriteLine("demand: \t{0}", string.Join("\t", demand));

Example Output:

buckets:        1       2       3
inventory:      20      16      56
supply:         10      9       44
demand:         4       7       23
Ibrahim Timimi
  • 2,656
  • 5
  • 19
  • 31
  • Bro one more doubt I want to print the elements of the dictionary frm above in a straight line one by one. like values of inventory in straight line then demand in a straight line, I tried using foreach loop like foreach (var kvp in inv_stored) {Console.Write("bucket :{0}\t", kvp.Key); Console.Write("inventory:{0}", kvp.Value);} but not working do i need to call for each element by element at() and print it via for loop – Specterhy Oct 16 '22 at 10:59
  • @Specterhy I have updated my answer to include printing all elements each in one line using a foreach loop. Hope it is the one you are looking for. Let me know if its not. Note: `kvp.Value` contains a whole element of class `data_inv`, you need to specify individual properties in that class such as `demand` to access its value. – Ibrahim Timimi Oct 16 '22 at 12:32
  • Thank you but I was looking for something like bucket: 0 0 0 and below that inventory comes like: inventory: 0 0 0, like we get output in a table but heading are on the side , I managed to do it with 3 for loops for now but any more way to do the same, I'm not able match the starting point of the first values column wise – Specterhy Oct 16 '22 at 14:40
  • @Specterhy I updated the answer with printing the elements into a table format. Note: `Select` is a `Linq` query that you can use to specify what data to return eg. if we want only the inventory values from all elements in dictionary, we can use `inv_stored.Values.Select(x => x.inventory)` – Ibrahim Timimi Oct 16 '22 at 15:14
  • @Specterhy Glad to hear that. If you don't want the tabs, you can print like this: `Console.WriteLine("inventory: {0}", string.Join(" ", inventory));` – Ibrahim Timimi Oct 16 '22 at 15:22
0

There's multiple problems with your code.

First, you can create a new record in a dictionary by doing something like dict[key] = value;. However, you can not do dict[key].field = value;. The setter can be used with non-existent keys, the getter can't.

Second, while you can use structs as values in a dictionary, you cannot set their fields directly. Structs use value-type semantics by default (i.e. whenever you don't explicitly use ref or take a pointer), so any change you made this way would be done to a copy of the struct, not the actual value in the dictionary. You can use something like this:

var val = dict[key];
val.field = newFieldValue;
dict[key] = val;

Third, it's generally considered bad practice to use mutable structs, exactly because of these complications. Mutable structs only have place in highly optimised code and native interop, and they need to be carefully tested and monitored. Heck, even many automated refactorings can break code with mutable structs.

Luaan
  • 62,244
  • 7
  • 97
  • 116