How much data is actually sent/saved when you reference one class in another? - c#

I have two classes, one has a lot of properties and the other has a couple. I need to reference a few of the properties of the larger class in the smaller class, but I'm wondering if it would be better to just pass the values down individually. Example:
public class LargeClass
{
private string _var1;
private string _var2;
private string _var3;
//...
private string _var20;
//stuff
}
public class SmallClass
{
private LargeClass _largeclass;
private string _var1;
public SmallClass(LargeClass LargeClass)
{
_largeclass = LargeClass;
_var1 = _largeclass.Var1 + _largeclass.Var2;
}
}
Or, I could do this for the small class and pass the values I need in directly:
public class SmallClass2
{
private string _var1;
private string _var2;
private string _var3;
public SmallClass2(string Var1, string Var2)
{
_var1 = Var1;
_var2 = Var2;
_var3 = _var1 + _var2;
}
}
Basically, my question is which one of these uses up less space (both while running and if serialized)?
Update: I was able to rewrite my classes so that the smaller class objects referenced their parent objects and found that it definitely did use less space when serialized. Obviously, this result is case by case, but for my code I basically changed it from each instance of the small class storing a file path as a string to having the class capable of creating the path string on the fly using references to the parent objects.
The resulting serialized data file was 55% smaller.

While running they will use the same amount of space since they are just reference variables (all point to the same memory location). If you are serializing the data - then you will see more overhead by serializing the larger class.

They will use nearly the same memory. Passing by reference creates a pointer to the object so no extra memory is used except the heap space required for the pointer. Regarding serialization, option B might take a bit less space if you use the standard binary serialization.

I would not be worrying about serialization space in this case (except if you have to serialize thousands of instances).
I'd be more focus on type usage and maintenance. For example if you want the smaller class to contain the values of the properties as they were at the time the instance was created then I'll copy the values. Otherwise, I'd use a reference to the larger type. This way the smaller type will get all changes on the fields. I'd also replace the "_var1 + _var2" with a property unless "_var1" and "_var2" never change.

Related

Do methods within structs negatively affect memorysize or performance in C#?

Introduction to the goal:
I am currently trying to optimize performance and memory usage of my code. (mainly Ram bottleneck)
The program will have many instances of the following element at the same time. Especially when historic prices should be processed at the fastest possible rate.
The struct looks like this in it's simplest way:
public struct PriceElement
{
public DateTime SpotTime { get; set; }
public decimal BuyPrice { get; set; }
public decimal SellPrice { get; set; }
}
I realized the performance benefits of using the struct just like an empty bottle and refill it after consumption. This way, I do not have to reallocate memory for each single element in the line.
However, it also made my code a little more dangerous for human errors in the program code. Namely I wanted to make sure that I always update the whole struct at once rather than maybe ending up with just an updated sellprice and buyprice because I forgot to update an element.
The element is very neat like this but I have to offload methods into functions in another classes in order to have the functionality I require - This in turn would be less intuitive and thus less preferable in code.
So I added some basic methods which make my life a lot easier:
public struct PriceElement
{
public PriceElement(DateTime spotTime = default(DateTime), decimal buyPrice = 0, decimal sellPrice = 0)
{
// assign datetime min value if not happened already
spotTime = spotTime == default(DateTime) ? DateTime.MinValue : spotTime;
this.SpotTime = spotTime;
this.BuyPrice = buyPrice;
this.SellPrice = sellPrice;
}
// Data
public DateTime SpotTime { get; private set; }
public decimal BuyPrice { get; private set; }
public decimal SellPrice { get; private set; }
// Methods
public decimal SpotPrice { get { return ((this.BuyPrice + this.SellPrice) / (decimal)2); } }
// refills/overwrites this price element
public void UpdatePrice(DateTime spotTime, decimal buyPrice, decimal sellPrice)
{
this.SpotTime = spotTime;
this.BuyPrice = buyPrice;
this.SellPrice = sellPrice;
}
public string ToString()
{
System.Text.StringBuilder output = new System.Text.StringBuilder();
output.Append(this.SpotTime.ToString("dd/MM/yyyy HH:mm:ss"));
output.Append(',');
output.Append(this.BuyPrice);
output.Append(',');
output.Append(this.SellPrice);
return output.ToString();
}
}
Question:
Let's say I have PriceElement[1000000] - will those additional methods put additional strain on the system memory or are they "shared" between all structs of type PriceElement?
Will those additional methods increase the time to create a new PriceElement(DateTime, buy, sell) instance, respectively the load on the garbage collector?
Will there be any negative impacts, I have not mentioned here?
will those additional methods put additional strain on the system memory or are they "shared" between all structs of type PriceElement?
Code is shared between all instances. So no additional memory will be used.
Code is stored separately from any data, and the memory for the code is only dependent on the amount of code, not how many instance of objects there are. This is true for both classes and structs. The main exception is generics, this will create a copy of the code for each type combination that is used. It is a bit more complicated since the code is Jitted, cached etc, but that is irrelevant in most cases since you cannot control it anyway.
I would recommend making your struct immutable. I.e. change UpdatePrice so it returns a new struct instead of changing the existing one. See why is mutable structs evil for details. Making the struct immutable allow you to mark the struct as readonly and that can help avoid copies when passing the struct with an in parameter. In modern c# you can take references to structs in an array, and that also helps avoiding copies (as you seem to be aware of).

How to make struct immutable inside a class definition

I have a question about creating an immutable struct inside a class definition. I want to define the struct outside the class but use that same struct type in the class definition while maintaining immutability. Will the code below achieve this?
namespace space
{
class Class1
{
public Struct {get; set;}
}
public Struct
{
public Struct(string strVar)
{
StructVar = strVar;
}
public string StructVar {get;}
}
}
Also, if I have a struct within a struct like:
class Class1
{
public Struct2 {get; set;}
}
public struct Struct2
{
public Struct2(string str, InStruct inStrct)
{
StrVar = str;
InStruct = inStrct;
}
public string StrVar {get;}
public InStruct InStruct {get;}
}
public struct InStruct
{
public InStruct(Array ary)
{
StrArray = ary
}
public Array StrArray {get;}
}
Does this also maintain immutability?
Lastly, if the size of the array in the InStruct is likely to be quite long, should I not use a struct at all and just put the array itself into the class definition instead? Am I just going struct crazy?
My concern is that because I'm doing a {set;} in the class definition that I'm breaking a rule somewhere. I would put the struct in the class definition itself but I didn't like to have to continuously call class constructors over and over to create each struct, that kind of seemed to defeat the purpose of using a struct in the first place.
It's a little difficult to give a complete answer without understanding exactly what you are trying to accomplish, but I'll start with a few important distinctions.
First, in C#, the struct/class distinction isn't about mutability per se. You can have a immutable class, like this one
public class CannotBeMutated
{
private string someVal;
public CannotBeMutated(string someVal)
{
_someVal = someVal
}
public string SomeVal => _someVal;
}
and a mutable struct, like this one
// This is not at all idiomatic C#, please don't use this as an example
public struct MutableStruct
{
private string _someVal;
public MutableStruct(string someVal)
{
_someVal = someVal;
}
public void GetVal()
{
return _someVal
}
public void Mutate(string newVal)
{
_someVal = newVal;
}
}
Using the above struct I can do this
var foo = new MutableStruct("Hello");
foo.mutate("GoodBye");
var bar = foo.GetVal(); // bar == "GoodBye"!
The difference between structs and classes is in variable passing semantics. When an object of a value type (e.g. a struct) is assigned to a variable, passed as a parameter to or returned from a method (including a property getter or setter) a copy of the object is made before it is passed to the new function context. When a object of a reference type is passed as a parameter to or returned from a method, no copy is made, because we only pass a reference to the object's location in memory, rather than a copy of the object.
An additional point on struct 'copying'. Imagine you have a struct with a field that is a reference type, like this
public struct StructWithAReferenceType
{
public List<string> IAmAReferenceType {get; set;}
}
When you pass an instance of this struct into a method, a copy of the reference to the List will be copied, but the underlying data will not. So if you do
public void MessWithYourSruct(StructWithAReferenceType t)
{
t.IAmAReferenceType.Add("HAHA");
}
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
MessWithYourSruct(s);
s.IAmAReferenceType.Count; // 1!
// or even more unsettling
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
var t = s; // makes a COPY of s
s.IAmAReferenceType.Add("hi");
t.IAmAReferenceType.Count; // 1!
Even when a struct is copied, its reference type fields still refer to the same objects in memory.
The immutable/mutable and struct/class differences are somewhat similar, insofar as they are both about where and whether you can change the contents of an object in your program, but they are still very distinct.
Now on to your question. In your second example, Class1 is not immutable, as you can mutate the value of Struct2 like this
var foo = new Class1();
foo.Struct2 = new Struct2("a", 1);
foo.Struct2 // returns a copy of Struct2("a", 1);
foo.Struct2 = new Struct2("b", 2);
foo.Struct2 // returns a copy of Struct2("b", 2);
Struct2 is immutable, as there is no way for calling code to change the values of StrVar or InVar once. InStruct is similarly immutable. However, Array is not immutable. So InStruct is an immutable container for a mutable value. Similar to if you had a ImmutableList<List<string>>. While you can guarantee calling code does not change the value of InStruct.StrArray to a different array, you can do nothing about calling code changing the value of the objects in the Array.
Finally, some generic advice related to your example.
First, mutable structs, or structs with mutable fields, are bad. The examples above should point to why structs with mutable fields are bad. And Eric Lippert himself has a great example of how terrible mutable structs can be on his blog here
Second, for most developers working in C# there's almost never a reason to create a user defined value type (i.e. a struct). Objects of value types are stored on the stack, which makes memory access to them very fast. Objects of reference types are stored on the heap, and so are slower to access. But in the huge majority of C# programs, that distinction is going to be dwarfed by the time cost of disk I/O, network I/O, reflection in serialization code, or even initialization and manipulation of collections. For ordinary developers who aren't writing performance-critical standard libraries, there's almost no reason to think about the performance implications of the difference. Heck, developers in Java, Python, Ruby, Javascript and many other languages get by in languages totally without user-defined value types. Generally, the added cognitive overhead they introduce for developers is almost never worth any benefit you might see. Also, remember that large structs must be copied whenever they are passed or assigned to a variable, and can actually be a performance problem.
TL;DR you probably shouldn't use structs in your code, and they don't really have anything to do with immutability.

Assigning value to member of nullable struct in C#

In C#, I have a struct like this:
public struct Slab
{ public float[] sizeM;
public string textureSrc;
//more members, not relevant here...
}
And another like this:
public struct Tombstone
{ public Slab mainSlab;
public Slab? basing;
//more...
}
Now, I want to modify members of basing:
uiState[0].stone.basing.Value.sizeM[2] = Int32.Parse(breadthField.Value) / 100.0f;
uiState[0].stone.basing.Value.textureSrc = fileName;
(uiState[0].stone is of type Tombstone)
First of these two calls works correctly, as I'm just changing a member of the array in basing, not the array itself. However, the second complains:
Cannot modify the return value of 'Slab?.Value' because it is not a variable
It works if I do the same to mainSlab which is not nullable. Is there a way to do this without copying the whole basing to a local variable for changes?
Is there a way to do this without copying the whole basing to a local variable for changes?
No, because Nullable<T> doesn't provide direct access to the underlying value field. You can't modify it "in place".
There are all kinds of little issues like this when you use mutable structs. I'd strongly advise you to use classes or immutable structs whenever possible, to avoid these corner cases.
Frankly, the main error here is almost certainly: having a mutable struct. Now, there are scenarios where mutable structs make sense, but those scenarios are narrow, and this almost certainly isn't one of them.
Frankly, your code will be much easier to rationalize if you stop doing that; with recent C#, you can even use readonly struct to help enforce this (and to get better behaviour with in):
public readonly struct Slab
{ public readonly float[] sizeM;
public readonly string textureSrc;
//more members, not relevant here...
}
(personally I'd also consider properties instead of public fields, but that is a separate issue)
Then it becomes obvious that you can only assign the entire object:
Slab? foo = ...
... some logic
foo = new Slab(size, textureSource); // perhaps taking new values from the old
The only other alternative is basically to do the same thing anyway:
Slab? foo = ...
// ...
var innerVal = foo.GetValueOrDefault(); // or .Value if you've already null-checked
// ...
innerVal.textureSrc = ...
foo = innerVal;
There may be many possible fixes for this "problem", depending on the rest of your design and requirements... For example:
public struct Tombstone
{
public Slab mainSlab;
public Slab basing;
public bool hasBasing => basing.sizeM != null;
//more...
}
To be honest I never user Nullables... Nullable value types, what's next, global rvalues?

Datastructure to represent extensible and unique values

I've a small problem. I've a application monitoring part in a framework which is used by multiple applications.
Right now I've a functionality like this:
public enum Vars
{
CPU,
RAM
}
public void Add(Vars variable, object value)
{
[...]
}
The Variable which is used as Parameter in the Add method will be used as the name of the entry in the database.
Now I got the requirement, that applications can specify own variables outside the framework. Because you can't inherit from an enum this causes some trouble.
I see basicly 2 possibilities (which are bot not very satisfying in my opinion) to solve this.
Possibility 1:
public void Add(enum variable, object value)
This method would accept all sorts of enums, so users could use the Vars enums as well as enums which they've defined by themself. The problem with this solution: It would be possible, that users use the same names in both.. application and framework. I'm not able to differ between two enums with the value "CPU" (Framework may store percent values as "CPU", application may store process cpu usage as "CPU").
Possibility 2:
The second method would be an class instead a enum, something like:
public class Vars
{
public const string CPU = "CPU";
public const string RAM = "RAM";
}
The drawbacks here:
1. More to write.
2. I would have to define parameters as strings:
public void Add(string variable, object value);
This could lead to missuse as well (Applications which add strings directly instead defining a class which inherits from Vars).
Any thoughts on how to define a model which:
Can be inherited (to extend the values by applicationspecific values)
Can be used as a parameter
Ensures, that there are no double (=same value) entries
?
The context is not completely clear, but what about creating a class
public class Vars
{
public static Vars CPU = Vars.Get("CPU", 1);
public static Vars RAM = Vars.Get("RAM", 2);
//You can keep one of the params, name or id
private Vars(string name, int id)
{
...
}
public static Vars Get(string name, int id)
{
//check if id or name exists in static dictionary, and return that instance or create new one
}
}
public void Add(Vars variable, object value);
Now user can create any kind of Parameter and pass to the method,
Vars newVar = Vars.Get("MyNewParam", 10);
You can easily check if the passed param is one, about which you know
Get method returns same instance if the params are the same

Exposing common values from a custom structure/type

One of my projects has a value type/struct that represents a custom identifier string for a video format. In this case, it's going to contain a content type string, but that can vary.
I've used a struct so it can be strongly type when it's passed around, and perform some sanity checks on the initial string value.
public struct VideoFormat {
private string contentType;
public VideoFormat(string contentType) {
this.contentType = contentType;
}
public string ContentType {
get { return this.contentType; }
}
public override string ToString() {
return this.contentType;
}
// various static methods for implicit conversion to/from strings, and comparisons
}
As there are a few very common formats, I've exposed these as static read only fields with default values.
public static readonly VideoFormat Unknown = new VideoFormat(string.Empty);
public static readonly VideoFormat JPEG = new VideoFormat("image/jpeg");
public static readonly VideoFormat H264 = new VideoFormat("video/h264");
Is it better to expose the common values as static read only fields or as get only properties? what if I want to change them later? I see both methods used throughout the .Net framework, e.g. System.Drawing.Color uses static readonly properties while System.String has a static read only field for String.Empty, and System.Int32 has a const for MinValue.
(Mostly copied from this question but with a more specific and not directly related question.)
Properties are a good idea unless you are declaring something that never changes.
With properties you can change the inside implementation without affecting programs consuming your library and handle changes / variations. Consuming programs wont break and wont require to be recompiled.
e.g. (I know this is a bad example but you get the idea..)
public static VideoFormat H264Format
{
get{
// This if statement can be added in the future without breaking other programs.
if(SupportsNewerFormat)
return VideoFormat.H265;
return VideoFormat.H264;
}
}
Also keep in mind that if you decided to change a field to a property in the future, consuming code breaks.

Categories