Using struct in dictionary as a value - c#

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

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.

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

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.

Related

Does C# have pointers to members like in C++?

In C++, you could write the following code:
int Animal::*pAge= &Animal::age;
Animal a;
a.*pAge = 50;
Is there similar functionality in C#?
Edit: To clarify, I am not asking about pointers. I am asking about "pointers to members", a feature found in C++ that is used with the .* and ->* operators.
Edit 2: Here is an example of a use case for members to pointers.
Let's say we have the following class:
class Animal
{
int age;
int height;
int weight;
…
}
And let's say that we want to write methods that will find the average age/height/weight/etc. of all Animals in an array. We could then do this:
int averageAge(Animal[] animals)
{
double average = 0;
for (…)
average += animals[i].age;
return average/animals.length;
}
int averageHeight(Animal[] animals)
{
//code here again
}
int averageWeight(Animal[] animals)
{
//code here again
}
We would end up copying and pasting a lot of code here, and if our algorithm for finding the average changed, we would encounter a maintenance nightmare. Thus, we want an abstraction of this process for any member. Consider something like this:
int averageAttribute(Animal[] animals, Func<Animal, int> getter)
{
double average = 0;
for (…)
average += getter(animals[i]);
return average/animals.length;
}
which we could then call with
averageAttribute(animals, (animal) => animal.age);
or something similar. However, using delegates is slower than it has to be; we are using an entire function just to return the value at a certain location in the Animal struct. In C++, members to pointers allow you to do pointer math (not the right term but I can't think of a better term) on structs. Just as you can say
int p_fourthAnimal = 3;
(animals + p_fourthAnimal)*
to get the value so many bytes ahead of the pointer stored in the variable animals, in C++, you could say
int Animal::* p_age = &Animal::age;
animal.*p_age //(animal + [the appropriate offset])*
to get the value so many bytes ahead of the pointer stored in the variable animal; conceptually, the compiler will turn animal.*p_age into (animal + [the appropriate offset])*. Thus, we could declare our averageAttribute as this instead:
int averageAttribute(Animal[] animals, Animal::* member)
{
double average = 0;
for (…)
average += animals[i].*member; //(animals[i] + [offset])*
return average/animals.length;
}
which we could then call with
averageAttribute(animals, &Animal::age);
In summary, pointers to members allow you to abstract a method such as our averageAttribute to all members of a struct without having to copy and paste code. While a delegate can achieve the same functionality, it is a rather inefficient way to get a member of a struct if you know you do not actually need the freedom allotted to you by a function, and there could even be edge use cases in which a delegate does not suffice, but I could not give any examples of such use cases. Does C# have similar functionality?
As other people have commented here, delegates are the way to achieve this in C#.
While a delegate can achieve the same functionality, it is a rather
inefficient way to get a member of a struct if you know you do not
actually need the freedom allotted to you by a function
It depends how the compiler and runtime implement that delegate. They could very well see that this is a trivial function and optimize the call away, like they do for trivial getters and setters. In F# for instance you can achieve this:
type Animal = { Age : int }
let getAge (animal:Animal) =
animal.Age
let inline average (prop:Animal->int) (animals:Animal[]) =
let mutable avg = 0.
for animal in animals do
avg <- avg + float(prop(animal)) // no function call in the assembly here when calling averageAge
avg / (float(animals.Length))
let averageAge = average getAge
You can get the same behaviour using delegates but that's not the same thing as delegates are pointers to functions in C++. What you're trying to achieve is possible in C# but not in the way you're doing in C++.
I think about a solution using Func:
public class Animal
{
public int Age { get; set; }
public int Height { get; set; }
public double Weight { get; set; }
public string Name { get; set; }
public static double AverageAttributeDelegates(List<Animal> animals, Func<Animal, int> getter)
{
double average = 0;
foreach(Animal animal in animals)
{
average += getter(animal);
}
return average/animals.Count;
}
}
List<Animal> animals = new List<Animal> { new Animal { Age = 1, Height = 2, Weight = 2.5, Name = "a" }, new Animal { Age = 3, Height = 1, Weight = 3.5, Name = "b" } };
Animal.AverageAttributeDelegates(animals, x => x.Age); //2
Animal.AverageAttributeDelegates(animals, x => x.Height); //1.5
It's working but you are bound to the int type of the property since the func is declared as Func<Animal, int>. You could set to object and handle the cast:
public static double AverageAttributeDelegates2(List<Animal> animals, Func<Animal, object> getter)
{
double average = 0;
foreach(Animal animal in animals)
{
int value = 0;
object rawValue = getter(animal);
try
{
//Handle the cast of the value
value = Convert.ToInt32(rawValue);
average += value;
}
catch(Exception)
{}
}
return average/animals.Count;
}
Example:
Animal.AverageAttributeDelegates2(animals, x => x.Height).Dump(); //1.5
Animal.AverageAttributeDelegates2(animals, x => x.Weight).Dump(); //3
Animal.AverageAttributeDelegates2(animals, x => x.Name).Dump(); //0
no, c# doesn't have a feature to point into (reference) object's members the way c++ does.
but why?
A pointer is considered unsafe. And even in unsafe area you cannot point to a reference or to a struct that contains references, because an object reference can be garbage collected even if a pointer is pointing to it. The garbage collector does not keep track of whether an object is being pointed to by any pointer types.
you mentioned a lot of duplicate code is used to implement it the non-pointer way, which isn't true.
Speed depends on how well the JIT compiles it, but you didn't test?
if you really run into performance problems, you need to think about your data structures and less about a certain way to access members.
If think the amount of comments under your Q shows, that you did not really hit a commonly accepted drawback of c#
var Animals = new Animal[100];
//fill array
var AvgAnimal = new Animal() {
age = (int)Animals.Average(a => a.age ),
height = (int)Animals.Average(a => a.height),
weight = (int)Animals.Average(a => a.weight)
};
the unsafe area of c# serves some ways access members by pointer, but only to value types like single structs and not for an array of structs.
struct CoOrds
{
public int x;
public int y;
}
class AccessMembers
{
static void Main()
{
CoOrds home;
unsafe
{
CoOrds* p = &home;
p->x = 25;
p->y = 12;
System.Console.WriteLine("The coordinates are: x={0}, y={1}", p->x, p->y );
}
}
}

Saving instructions for later evaluation, possible?

I want to save "instructions" for how a value should be determined at a later time, instead of saving the actual value at the current time.
Is this even possible?
A simple C# example:
int[] myArray = new int[2];
Dictionary<string, int> myDictionary = new Dictionary<string, int>();
//dictionary type can be changed if required
myArray[0] = 1;
myArray[1] = 2;
myDictionary.Add("total", (myArray[0] + myArray[1]) ); // Don't evaluate the value now
myArray[0] = 3;
myArray[1] = 4;
Console.WriteLine("total 2 = " + myDictionary["total"]); // Evaluate the value now
//Desired output: 7 (3+4), actual output = 3 (1+2)
You could use (expression bodied read-only) properties:
public int[] MyArray { get; set; }
public string CurrentResult => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";
You can use local functions if you need local variables:
string GetCurrentResult() => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";
MyArray[0] = 1;
MyArray[1] = 2;
Console.WriteLine(GetCurrentResult()); // total: 3 (1+2)
MyArray[0] = 3;
MyArray[1] = 4;
Console.WriteLine(GetCurrentResult()); // total: 7 (3+4)
If you don't use C#7 you could use a Func<string> delegate:
Func<string> GetCurrentResult = () => $"total: {MyArray.Sum()} ({string.Join("+", MyArray)})";
You are looking for Lazy<T>. It takes a Func<T> that doesn't evaluate until it is accessed via the Value property. Once it is evaluated, the result is stored for further access. So your code might look something like:
int[] myArray = new int[2];
var total = new Lazy<int>(() => myArray.Sum());
myArray[0] = 1;
myArray[1] = 2;
myArray[0] = 3;
myArray[1] = 4;
Console.WriteLine("total = " + total);
Console.WriteLine("total = " + total.Value);
Console.WriteLine("total = " + total);
The output of this code is:
total = Value is not created.
total = 7
total = 7
Note that, without calling total.Value, the result is not an int but rather a message telling us the expression hasn't been evaluated yet. Once total.Value has been called, subsequent accesses to total yield the value (due to implicit ToString() call in the Console.WriteLine()).
The benefit of using Lazy<T> is that the value is persisted, instead of being recalculated each time it is accessed. This makes it great for properties/fields in classes that may not be accessed each time the class is used but take a long time to generate a value.
Edit: Based on Op's feedback Lazy<T> isn't exactly what they are looking for.
If you always want to evaluate the expression each time it is accessed, you want a method or Func<T>. So imagine you have a class like this:
public class MyClass
{
public int[] Vals {get;set;}
}
If you want to define a custom way of getting the (for example) sum of Vals, you have a couple of simple options.
A Class method
public class MyClass
{
public int[] Vals {get;set;}
public int SumOfVals()
{
return Vals.Sum();
}
}
If you opt for the class method, you could (conceivably) make the class generic (MyClass<T>) and use a virtual/abstract method to implement the concrete SumOfVals method.
A Func<T> implemented in the Class
public class MyClass
{
public int[] Vals {get;set;}
public Func<int[], int> SumOfVals { get;set; }
}
Now you can set SumOfVals to some custom function each time the class is instantiated. If you don't set it to anything, you'll get a NullReferenceException if you try to do anything with it.
A Func<T> implemented inline
var vals = new int[2];
var sumVals = new Func<int[], int>((arr) => arr.Sum());
Console.WriteLine(sumVals(vals));
This is probably the most flexible, but this can lead to some spaghetti code. I would recommend just creating either a method in the class that calls into MyClass or creating a method in MyClass to handle this logic.

Getting Value from dictionary, when the key in an object

I have an object PixelData:
public class PixelData
{
public int X {get;set;}
public int Y {get;set;}
}
pixel data is a key to a dictionary.
Dictionary<PixelData, int> dict
how do i use pixel data the right way?
A very simple solution would be to use a struct instead of a class for PixelData:
public struct PixelData
{
public int X;
public int Y;
}
var dict = new Dictionary<PixelData, int>();
You can read about the differences between structs and classes in C# here. Short version: structs are value types, unlike classes which are reference types. Therefore, if you want to retrieve a value from the dictionary, you don't need a reference to the original PixelData instance which was used as the key. You can go ahead and create a new instance, with the exact same X and Y you used for the key, and it will work just fine.
// Add new value to dictionary with new PixelData instance as the key
dict.Add(new PixelData { X = 1, Y = 1 }, 42);
// Retrieving the value using a new, but identical instance of PixelData works just fine
int value = dict[new PixelData { X = 1, Y = 1 }]);
If X and Y are public properties, then below query can be used to retrieve the matching dictionary value. This query assumes that 'searchingForItem' is the PixelData Item, you are looking to find in dict.
var matchingItem = dict.FirstOrDefault(p => p.Key.X.Equals(searchingForItem.X) && p.Key.Y.Equals(searchingForItem.Y));

Modifying values within a list

I've been trying to write a program which can scan a raw data file and normalize it for data mining processes, I've trying to read the data from the file and store it in a list this way:
public static List<Normalize> NF()
{
//Regex r = new Regex(#"^\d+$");
List<Normalize> N = new List<Normalize>();
StreamReader ss = new StreamReader(#"C:\Users\User\Desktop\NN.txt");
String Line = null;
while (!ss.EndOfStream) {
Line = ss.ReadLine();
var L = Line.Split(',').ToList();
N.Add(new Normalize { age = Convert.ToInt16(L[0]),
Sex = L[1],
T3 = Convert.ToDouble(L[2]),
TT4 = Convert.ToDouble(L[3]),
TFU = Convert.ToDouble(L[4]),
FTI = Convert.ToDouble(L[5]),
RC = L[6],
R = L[7]
});
}
return N;
}
}
struct Normalize {
public int age;
public String Sex;
public double T3;
public double TT4;
public double TFU;
public double FTI;
public String RC;
public String R;
}
At this moment I want to go through the list that I've made and categorize the data , similar to this :
var X= NF();
for (int i = 0; i < X.Count; i++) {
if (X[i].age > 0 && X[i].age <= 5) { // Change the X[i].age value to 1 }
else if (X[i].age > 5 && X[i].age <= 10) { // Change the X[i].age value to 2 }
...
}
But the compiler says X[i].[variable name] is not a variable and cannot be modified in this way. My question is, what would be an efficient way to perform this operation.
struct Normalize is a value type, not a reference type, therefore you cannot change its fields like that. Change it to class Normalize
Change struct Normalize to class Normalize and iterate with foreach loop. It's way cleaner.
You could also set variables to private and use getters/setters to check/set variable.
foreach (Normalize x in X)
{
if (x.getAge() > 0 && x.getAge() <= 5)
x.setAge(1)
...
}
Edit:
just saw you already got your answer
Modifying struct field is fine as long as it's a single entity (Given its a mutable struct). This is possible -
var obj = new Normalize();
obh.Age = 10;
But in your case you are accessing the struct using indexer from the list.
Indexer will return copy of your struct and modifying the value won't reflect it back to the list which ain't you want.
Hence compiler is throwing error to stop you from writing this out.
As Alex mentioned, you should go for creating class instead of struct if you want to modify it.
On a side note, its always advisable to have immutable structs instead of mutable structs.

Declare static classes so that they can be stored within List

I am developing a software that takes realtime-data and extracts a number of features from that depending on user input. Each available feature consists of one method that takes an array of doubles and return the wanted feature, such as this one for the MeanAbsoluteValue:
public static class MeanAbsoluteValue{
public static double Calculate(double[] data){
return data.Sum(s => Math.Abs(s)) / data.Length;
}
}
Since each of the features only has the one Calculate method I was thinking of trying to rewrite them so that they can be collected and chosen from that Collection.
I have tried writing an Interface for them to use, but since they are static this was not allowed.
Is there a way of doing this? And if so, could you point me in the right direction?
You can create an array of delegates constructed from the Calculate methods of these classes, like this:
Func<double[],double>[] array = new Func<double[],double>[] {
MeanAbsoluteValue.Calculate
, MeanValue.Calculate
, Deviation.Calculate
// ...and so on
};
Here is a demo on ideone.
Store delegates to your functions in a dictionary, and look them up by name
var methods = new Dictionary<string, Func<double[], double>>();
methods.Add("MeanAbsoluteValue", MeanAbsoluteValue.Calculate);
...
public double DoFunc(string name, double [] args)
{
var func = methods[name];
return func(args);
}
Just have a collection of Func...
var list = new List<Func<double[], double>(MeanAbsoluteValue.Calculate, Average.Calculate)
var accum = 0;
foreach(var func in list)
{
accum += func(new [] {1,3,4,});
}

Categories

Resources