There are several much more complicated answers out there to a simple question I have, so I'll ask the question in regards to my situation because i can't quite figure out what to do based off of those other answers. Garbage collection seems like a danger zone, so I'll err on the side of caution.
I have a Measurement object that contains a Volume object and a Weight object. Depending on which constructor is used, I would like to destroy the opposite object, that is to say, if a user adds a volumetric measurement, I would like to eradicate the weight element of that instance, as it is just bloat at that point. What should be done?
Edited for clarification:
public class RawIngredient
{
public string name { get; set; }
public Measurement measurement;
public RawIngredient(string n, double d, Measurement.VolumeUnits unit)
{
name = n;
measurement.volume.amount = (decimal)d;
measurement.volume.unit = unit;
//I want to get rid of the weight object on this instance of measurement
}
public RawIngredient(string n, double d, Measurement.WeightUnits unit)
{
name = n;
measurement.weight.amount = (decimal)d;
measurement.weight.unit = unit;
//I want to get rid of the volume object on this instance of measurement
}
}
Edited again to show Measurement
public class Measurement
{
public enum VolumeUnits { tsp, Tbsp, oz, cup, qt, gal }
public enum WeightUnits { oz, lb }
public Volume volume;
public Weight weight;
}
Volume and Weight are simple classes with two fields.
First of all, what needs to be destroyed? This is happening in the ctor, so just don't create the one you don't want.
class Measurement
{
public Volume Volume {get; set;}
public Weight Weight {get; set;}
public Measurement (Volume v) { Volumme = v; Weight = null;}
public Measurement (Weight w) { Volumme = null; Weight = w;}
}
If you are in the Measurement constructor, then simply don't create the non-required type; it will remain as the default value of null (as long as Volume and Weight are reference types and not structs), and any attempted reference to the wrong type would throw an exception.
As long as the Measurement object is in scope, the garbage collector couldn't collect the non-required type, as it would be in the scope of the Measurement instance, and could theoretically be created at any time, regardless of your actual intentions in reality.
If the objects implement IDisposable, you should call their Dispose method and ensure that they're not referenced or disposed-of again.
After Dispose-ing (if necessary), you can set the unused object to null.
Reference: http://blog.stephencleary.com/2010/02/q-should-i-set-variables-to-null-to.html
Related
i've a Method which gets a List where T : Item.
How do i access the property from the Subclasses of Item?
private void CreateShopItem<T>(Transform itemTemplate, Transform shopScrollView, List<T> shopItemList)
where T : Item {
shopItemList.Name //this works
shopItemList.power //this is a property from the class cooling and i cant access it
}
Ive 4 subclasses from the base class Item but i can only access the properties from the Class Item
Item Class:
public class Item
{
public int Id;
public string Name;
public double Cost;
public Sprite Sprite;
public bool IsPlaced;
public Vector3 Position;
public Item()
{
Id = 0;
Name = "Default";
Cost = 0;
Sprite = null;
IsPlaced = false;
Position = Vector3.zero;
}
public Item(int id, string name, double cost, Sprite sprite, bool isPlaced, Vector3 position)
{
this.Id = id;
this.Name = name;
this.Cost = cost;
this.Sprite = sprite;
this.IsPlaced = isPlaced;
this.Position = position;
}
}
Sub Class Cooling:
public class Cooling : Item
{
public float power;
public float temp;
public Cooling(int id, string name, double cost, Sprite sprite, bool isPlaced, Vector3 position,
float power, float temp)
{
base.Id = id;
base.Name = name;
base.Cost = cost;
base.Sprite = sprite;
base.IsPlaced = isPlaced;
base.Position = position;
this.power = power;
this.temp = temp;
}
}
What would be a way to access the property of all subclasses from the Base Class?
Normally if a method needs to access a field/property this field would be included in the type that it accepts. While you can cast the item into a derived type, if you have to do it why accept the base type in the first place?
The problem is that if you use ifs or case when you add a new type you need to remember to come back to this piece of code and update it.
BTW. Use properties, not fields. It is the standard way:
public class Item
{
public int Id { get };
What you're asking the code to do doesn't make logical sense. When you use a generic type:
public class Foo<T>
{
public T Value { get; set; }
public void MyMethod()
{
// example code here
}
}
You are saying that you're going to be using a type (T) but you're not really sure yet which type you'll be using. The type will be specified at a later stage. The only assumption made by the compiler is that your T will derive from object.
This is okay, but that also means that you can't actually use this T with any more precision than you can use object. In the above example, you could call this.Value.ToString() because T is definitely an object (and object has the ToString() method), but you cannot call this.Value.Power because T is not known to be of the type Cooling (or a subtype).
You are able to influence what the compiler knows about the specific type that T will be. You've already done so by specifying that T will definitely be some sort of Item (i.e. class or subclass)
public class Foo<T> where T : Item
{
public T Value { get; set; }
public void MyMethod()
{
// example code here
}
}
Because the expectation is now that T is not just an object but also an Item, the compiler allows you to handle your T type with every known property/method of the Item type. You could access things like:
this.Value.Name
this.Value.Cost
this.Value.Sprite
Because these are properties of the Item class which you can definitely expect to see on any subclass of Item, you are allowed to access them when dealing with a T where T : Item generic type parameter.
You're trying to access a specific type's property (Cooling), without having told the compiler that your generic type is definitely going to be a (sub) class of Cooling.
That directly contradicts the core premise of using a generic type, i.e. treating a range of possible types using the same (generic) code. If that generic code were to only work with one specific type (i.e. Cooling), then there'd be no point in trying to make CreateShopItem work for any type that is not Cooling or one of its subtypes.
You need to go back to the drawing board with what it is that you want.
If I can assume that it is correct that CreateShopItem should work for any Item class, then you should inherently be able to write code that is able to handle any Item object without needing to know the specific concrete class being used.
I am very intentionally ignoring upcasting here because it's a bad approach that tries to cover for a bad design. Generic type upcasting is rarely a good idea. It violates OCP (in all but exceedingly rare examples), and would not be a good idea in this particular scenario anyway.
First of all the example that you show for the this one works and this one doesn't should be wrong because the reference that you are using is a List (List for your example) and the both of them will not work unless you get the element that you want to change from that list (with a loop or maybe with LINQ First() etc)
Secondly, If you want to access a field from a subclass while you have a base class object. You need to cast it to that subclass. For example:
class Item{
...
public int Id;
public string Name;
public double Cost;
}
class Cooling : Item {
...
public float power;
}
//Example method to call
private void CreateShopItem<T>(Transform itemTemplate, Transform shopScrollView, List<T> shopItemList)
where T : Item {
var firstItem = shopItemList().First(); // taking the first element just for example
firstItem.Name = "foo"; // this is fine
var coolingItem = (Cooling) firstItem;
coolingItem.power = 1000; // now this is also fine
}
This will fix your current case but I do not recommend to do it because as the subclasses increase this can turn into a big mess of casting disaster between classes.
I recommend to check out boxing/unboxing topic on C# for future use and best practices.
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).
I have developed a fairly complex spreadsheet in Excel, and I am tasked with converting it to a C# program.
What I am trying to figure out is how to represent the calculations from my spreadsheet in C#.
The calculations have many dependencies, to the point that it would almost appear to be a web, rather than a nice neat hierarchy.
The design solution I can think of is this:
Create an object to represent each calculation.
Each object has an integer or double, which contains the calculation.
this calc has inputs from other objects and so requires that they are evaluated first before it can be performed.
Each object has a second integer "completed", which evaluates to 1 if the previous calculation is successful
Each object has a third integer "ready"
This item requires all precedent object's "completed" integers evaluate to
"1" and if not, the loop skips this object
A Loop runs through all objects, until all of the "completed" integers = 1
I hope this makes sense. I am typing up the code for this but I am still pretty green with C# so at least knowing i'm on the right track is a boon :)
To clarify, this is a design query, I'm simply looking for someone more experienced with C# than myself, to verify that my method is sensible.
I appreciate any help with this issue, and I'm keen to hear your thoughts! :)
edit*
I believe the "completed" state and "ready" state are required for the loop state check to prevent errors that might occur from attempts to evaluate a calculation where precedents aren't evaluated. Is this necessary?
I have it set to "Any CPU", the default setting.
edit*
For example, one object would be a line "V_dist"
It has length, as a property.
It's length "V_dist.calc_formula" is calculated from two other objects "hpc*Tan(dang)"
public class inputs
{
public string input_name;
public int input_angle;
public int input_length;
}
public class calculations
{
public string calc_name; ///calculation name
public string calc_formula; ///this is just a string containing formula
public double calculationdoub; ///this is the calculation
public int completed; ///this will be set to 1 when "calculationdoub" is nonzero
public int ready; ///this will be set to 1 when dependent object's "completed" property = 1
}
public class Program
{
public static void Main()
{
///Horizontal Length
inputs hpc = new inputs();
hpc.input_name = "Horizontal "P" Length";
hpc.input_angle = 0;
hpc.input_length = 200000;
///Discharge Angle
inputs dang = new inputs();
dang.input_name = "Discharge Angle";
dang.input_angle = 12;
dang.input_length = 0;
///First calculation object
calculations V_dist = new calculations();
V_dist.calc_name = "Vertical distance using discharge angle";
V_dist.calc_formula = "hpc*Tan(dang)";
**V_dist.calculationdoub = inputs.hpc.length * Math.Tan(inputs.dang.input_angle);**
V_dist.completed = 0;
V_dist.ready = 0;
}
}
It should be noted that the other features I have yet to add, such as the loop, and the logic controlling the two boolean properties
You have some good ideas, but if I understand what you are trying to do, I think there is a more idiomatic -- more OOP way to solve this that is also much less complicated. I am presupposing you have a standard spreadsheet, where there are many rows on the spreadsheet that all effectively have the same columns. It may also be you have different columns in different sections of the spreadsheet.
I've converted several spreadsheets to applications, and I have settled on this approach. I think you will love it.
For each set of headers, I would model that as a single object class. Each column would be a property of the class, and each row would be one object instance.
In all but very rare cases, I would say simply model your properties to include the calculations. A simplistic example of a box would be something like this:
public class Box
{
public double Length { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Area
{
get { return 2*Height*Width + 2*Length*Height + 2*Length*Width; }
}
public double Volume
{
get { return Length * Width * Height; }
}
}
And the idea here is if there are properties (columns in Excel) that use other calculated properties/columns as input, just use the property itself:
public bool IsHuge
{
get { return Volume > 50; }
}
.NET will handle all of the heavy lifting and dependencies for you.
In most cases, this will FLY in C# compared to Excel, and I don't think you'll have to worry about computational speed in the way you've set up your cascading objects.
When I said all but rare cases, if you have properties that are very computationally expensive, then you can make these properties private and then trigger the calculations.
public class Box
{
public double Length { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Area { get; private set; }
public double Volume { get; private set; }
public bool IsHuge { get; private set; }
public void Calculate()
{
Area = 2*Height*Width + 2*Length*Height + 2*Length*Width;
Volume = Length * Width * Height;
IsHuge = Volume > 50;
}
}
Before you go down this path, I'd recommend you do performance testing. Unless you have millions of rows and/or very complex calculations, I doubt this second approach would be worthwhile, and you have the benefit of not needing to define when to calculate. It happens when, and only when, the property is accessed.
So basically I have this one class called Animal.
In this class I have strings a,b,c,x,y,z;
I want to make an object array for this program so I make one called arr.
For a,b,c,x and y I want to have different values for each object array elements.
I.e.: arr[0].a will be different than arr[1].a, which is different than arr[2].a etc.
However, for the property z, I only want to use one value for the whole of the program, I.e: arr[0].z is the only z value that I want to use. Currently I just call arr[0].z and never use any other number in [].
Is this bad practice and should I make a whole new class, just for property z so that I don't waste memory space? Are there any other problems associated with not using any of the other values of z?
Make the z variable static and in the constructor of you class simply initialize with this value.
You can implement your class in this way.
public class Animal
{
public string A { get; } // related to instance
public string B { get; }
public string C { get; }
public string X { get; }
public string Y { get; }
public string Z // gets or sets static variable which will affect all animals.
{
get { return _z; }
set { _z = value; }
}
private static string _z;
}
Is this bad practice ?
Without context we cant say its always bad design or not. But generally, yes its bad design.
I'm running into an issue with Xml serialization of my own class. It is a derived class, which doesn't naturally have a parameterless constructor - I had to add one just for the sake of serialization. Of course, because of that I'm running into dependency/order issue.
Here's a simplification, which I hope still illustrates the problem (I reserve the right to augment the illustration if it turns out I didn't capture the problem - I just didn't want to dump a complicated Object Model on you :))
public class Base{
public virtual Vector Value{ get; set;}
}
public class Derived : Base{
public Vector Coefficient { get; set; }
public override Vector Value{
get { return base.Value * Coefficient; }
set { base.Value = value / Coefficient; }
}
}
EDIT: to avoid confusion, I substituted the value type double in the original post with a not-shown-here Vector type
When XmlSerializer de-serializes Derived, I run into null value exception - Both base.Value and this.Coefficient are null.
Is there any way to fix this?
It seems that a lot of the issues here stem from using your domain model for serialization. Now, this can work, but it can also be hugely problematic if your domain model deviates even slightly from what the serializer wants to do.
I strongly suggest trying to add a second parallel representation of the data, as a "DTO model" - meaning: a set of objects whose job is to represent the data for serialization. S instead of a complicated property with calculations and dependencies, you just have:
public double SomeValue { get; set; }
etc. The key point is that is is simple and represents the data, not your system's rules. You serialize to/from this model - which should not be simple - and you map this to/from your domain model. Conversion operators can be useful, but a simple "ToDomainModel" / "FromDomainModel" method works fine too. Likewise, tools like AutoMapper might help, but 15 lines of DTO-to/from-Domain code isn't going to hurt either.
This avoids issues with:
constructors
non-public members
assignment order
read-only members
versioning
And a range of other common pain points in serialization.
You need to tell the serializer that your base object has derived items. Try:
[XmlInclude(typeof(Derived))]
public class Base {
Alternatively, you can explain this at run time with:
public XmlSerializer(Type type, Type[] extraTypes){..}
In your case: new XmlSerializer(typeof(Base), new Type[] { typeof(Derived), ..});
And to make things even more generic, if there is a huge hierarchy, you can use reflection to get a list of the derived types:
// You'll want to cache this result, and it could be a lot of work to run this
// multiple times if you have lots of classes
var knownTypes = Assembly.GetExecutingAssembly().GetTypes().Where(
t => typeof(Base).IsAssignableFrom(t)).ToArray();
var serializer = new XmlSerializer(typeof(Base), knownTypes);
One problem with your Value getter and setter is that if Coefficient is not loaded at the time when de-serializing the Value, then it will cause divide by zero errors. Even worse, it might not break, but instead, actually do the calculation against an incorrect value since Coefficient may have a pre-deserialization value stored in it. The following will solve the divide by zero situation, and hopefully update value correctly if coefficient loads second. In truth, these situations are usually handled better by serializing the non calculated value and then using [XmlIgnoreAttribute] on the derived property.
public class Derived : Base{
public override double Value{
get { return _coefficient; }
set {
if(Coefficient == 0){
base.Value = value;
}else{
base.Value = value / Coefficient;
}
}
private double _coefficient;
public double Coefficient{
get { return _coefficient; }
set {
if(Coefficient == 0)
{
temp = base.Value;
_coefficient = value;
Value = temp;
}
else{
_coefficient = value;
}
}
}
// Example by serializing unmodified value
public double Coefficient { get; set; }
public double BaseValue { get; set; }
[XmlIgnoreAttribute]
public double Value
{
get { return BaseValue * Coefficient; }
set
{
if(Coefficient != 0){
BaseValue = value / Coefficient;
}else{
BaseValue = value;
}
}