public class Price
{
public string Symbol {get; set; }
public double AskPrice{get; set; }
public double BidPrice{get; set; }
public string Exchange{get; set; }
}
public class inputs
{
public IList<Price> Prices {get; set; }
}
var inputs = new
{
Prices = prices,
};
Price[] p = inputs.Prices.Where(x => x.Exchange == exchange).ToArray();
p.ForEach(x => x.AskPrice = 0);
For this code when I create new variable p, it is actually a reference to input.price, not a new variable. Why is this? Is there any best practice of how to deal with this behavior?
You did not make a change to p, p stayed the same, what you changed where the elements inside of p, the elements inside of p are shared between p and the original source.
To not get this behavior you need to "Deep copy" the objects when you make a new array, creating new objects for the elements with the same content as the original.
public class Price
{
public string Symbol {get; set; }
public double AskPrice{get; set; }
public double BidPrice{get; set; }
public string Exchange{get; set; }
public Price Clone()
{
var result = new Price();
result.Symbol = this.Symbol;
result.AskPrice = this.AskPrice;
result.BidPrice = this.BidPrice;
result.Exchange = this.Exchange;
return result;
}
}
public class inputs
{
public IList<Price> Prices {get; set; }
}
var inputs = new
{
Prices = prices,
};
Price[] p = inputs.Prices.Where(x => x.Exchange == exchange).Select(x=> x.Clone()).ToArray();
p.ForEach(x => x.AskPrice = 0);
Note, if you have any reference types inside of your class you need to recursively clone the entire data structure and will need to make copies of them too.
There are two different variables here - the first is the Price object(s), and the second is input.Prices, which is a List of prices.
Your LINQ code takes the inputs.Prices list, filters it and creates a new array from it, but all that does is create new collections. It doesn't change the actual objects that are in the collection. This is because classes, in C#, are all reference types, meaning that var price = input.Prices[0] just copies the reference to a single, specific instance in memory. You can copy those references between a dozen lists and arrays, but the objects are the same.
It seems that what you want is to clone or copy by value your Price objects. For that, you have two options:
Make Price a struct.
Structs, unlike classes, are value types and are copied-by-value, meaning a new copy is made whenever you assign it to a new variable. This, however, has a performance penalty, since the whole struct is copied every time it's assigned. Your struct takes up 24-32 bytes (two 64bit doubles and two 32/64 bit references to strings), which is more than the recommended rule of thumb of "no more than 16 bytes for structs", so it's probably a bad idea.
Make a Clone method.
Have your Price implement a Clone method which returns a copy of the object - or alternately, create a copy-constructor that creates a new Price with the old values. Use that in your LINQ:
public class Price
{
// your fields
public Price Clone()
{
return new Price
{
Symbol = this.Symbol,
BidPrice = this.BidPrice,
//etc.
}
}
}
var p = input.Prices.Where(x => x.Exchange == exchange).Select(x => x.Clone()).ToArray();
Related
I have two types:
public class SubCategories
{
public static List<SubCategories> subCategories = new List<SubCategories>();
public string title { get; set; }
public string IDfromCategories { get; set; }
public string subCategoryID { get; set; }
public bool isChecked { get; set; }
}
public class UserInsideCategories
{
public string userEmail { get; set; }
public string iDfromSubCategories { get; set; }
}
And two lists both containing this object multiple times.
Now I wanna go through a list with type SubCategories and check each object, if it contains the same value as my other list of type UserInsideCategories. Specifically, I wanna know if any object on the list.SubcategoryID is equal to any object on the other list.IdFromSubCateogires.
I achieved this like so:
List<SubCategories> branch = new List<SubCategories>();
for(int i = 0; i < subCategories.Count; i++)
{
SubCategories e = new SubCategories();
for(int x = 0; x < allSubs.Count; x++)
{
if (e.IDfromCategories == allSubs[x].iDfromSubCategories)
e.isChecked = true;
}
branch.Add(e);
}
So I am using a nested loop. But since I have to do this multiple times, it takes far too long.
I also thought about turning all values from SubCategories into a simple string array and use the Contains function, to see if the current object.IDfromCategories contains the object on the array. This would mean I would NOT use a for loop. But interenally, I believe, the system is still using a loop and therefore there would be no performance benefit.
What would be the best way of checking each object if it contains a value from the other list?
You should use some kind of lookup table. Probably either HashSet or Dictionary. The former only allows checking if a key exists in the set, while the later allows you to also find the object the key belongs to.
To check all the UserInsideCategories that shares an id with a SubCategories you could write:
var dict = subCategoriesList.ToDictionary(s => s.subCategoryID, s => s);
var matches = userInsideCategoriesList.Where(l => dict.ContainsKey(l.iDfromSubCategories));
if you want matching pairs you could write:
foreach (var user in userInsideCategoriesList)
{
if (dict.TryGetValue(user.iDfromSubCategories, out var subCategory))
{
// Handle matched pairs
}
}
This assumes that the ID is unique in respective list. If you have duplicates you would need something like a multi-value dictionary. There are no multi-value dictionary built in, but I would expect there are some implementations if you search around a bit.
Say I have a dictionary of Something:
private Dictionary<uint, Something> _somethingList = new Dictionary<uint, Something>();
Something being, for example:
class Something
{
public uint Id { get; set; }
public string Name { get; set; }
// ... more stuff here
}
And then I have Another class:
class Another
{
public Another(uint id, string name, Something connection)
{
Id = id;
Name = name;
Connection = connection;
}
public uint Id { get; set; }
public string Name { get; set; }
public Something Connection { get; set; }
}
And using it like this:
var test = new Another(1, "Test", _somethingList[1]);
Will Connection be a reference or copy of the value with key 1 from the _somethingList dictionary or it will create a new memory for it?
I guess what I am asking is, how it would behave in memory, as in, would it duplicate the property data in memory or would it be like a pointer to the actual _somethingList[1]? Or how can I verify this myself(I mean if I break point is there something that indicates whether its a copy or reference or w/e)?
With your data structure and class design, If you perform following line of codes. You will get to know that, in property Connection of Another class you are actually having a reference of _somethingList[1] not a copy.
Editing my Answer with profiler result so you can get the idea of Memory usage too
changed something class (which is just to magnify memory usage and you don't have to consider it in your actual code.
public class Something
{
public uint Id { get; set; }
public string Name { get; set; }
public List<string> stringList { get; set; }
public Something (uint id, string name)
{
Id = id;
Name = name;
stringList = new List<string>();
for(long i = 0; i < 10000; i++)
{
stringList.Add(i.ToString());
}
}
}
and logic is,
DateTime nowDateTime = DateTime.Now;
Dictionary<uint, Something> _somethingList = new Dictionary<uint, Something>();
Console.WriteLine((DateTime.Now - nowDateTime).TotalSeconds.ToString() + " Creating List _somethingList");
//slowly creating lsit so you can get memory usage incresing in profiler
for (uint i = 1; i < 10; i++)
{
_somethingList.Add(i, new Something(i, "amit" + i.ToString()));
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine((DateTime.Now - nowDateTime).TotalSeconds.ToString() + " Before creating test object");
System.Threading.Thread.Sleep(5 * 1000);
Another test = new Another(1, "Test", _somethingList[1]);
Console.WriteLine((DateTime.Now - nowDateTime).TotalSeconds.ToString() + " After creating test object");
Console.WriteLine((DateTime.Now - nowDateTime).TotalSeconds.ToString() + " Name before editing:" + test.Connection.Name);
_somethingList[1].Name = "EditedName";
Console.WriteLine((DateTime.Now - nowDateTime).TotalSeconds.ToString() + " Name after editing:" + test.Connection.Name);
and output is,
you can see, on creating every object of somethingList there is significant increment of memory usage in profiler observation,
but from second 9 to 14, when we are setting reference of _somethingList[1] to Connection there is no memory increasing in profiler result. that means it was just reference setting no memory allocation.
All classes in .net are reference types, therefore you will have a reference to the same dictionary entry and not a copy of it. if you're looking for a copy then use scruct instead of the class. structs are value types but have smaller scope and more limited behavior when compared to classes.
If you in fact need to copy by value and keep the class then you probably can benefit from some deep cloning method and clone you're object before passing onto the constructor. there are numerous implementations of deep and shallow clone out there and you can easily find one online.
There are 2 basic types: Reference and value. Dictionary is not important because you extract a value from Dictionary and pass that.
_somethingList[1] => returns Something object which in turns get's passed to Another.ctor
Think of it as:
Something somethingObj = _somethingList[1];
var test = new Another(1, "Test", somethingObj);
The way these objects behave in memory is a bit tricky. You are working in a managed language which means you don't have direct control over the memory or optimizations.
You can check for identity and equality. Identity means the locations (a location is loosely a memory address with a type) are the same. If two objects have the same identity then they are also always equal. Equality means the values stored in the variables are the same, but the variables themselves may or may not be stored in the same location.
Identity can be checked using Object.ReferenceEquals.
Equality can be checked using Object.Equals.
In this example I show how you can check for identity and equality against Something.
void Main()
{
var a = new Something();
var b = a;
var c = new Something();
Object.Equals(a,b);//True
Object.Equals(b,c);//False
Object.Equals(a,c);//False
Object.ReferenceEquals(a,b);//True
Object.ReferenceEquals(b,c);//False
Object.ReferenceEquals(a,c);//False
var d = M(a);//Pass a to M and check the identity of what comes back
Object.ReferenceEquals(a, d);//True
}
public static Something M(Test e)
{
e.SomeVariable = 10;//a and e now refer to the same object location
//e = new Test();//a and e refer to different objects when you do this. This will not be reflected back to the caller unless you use ref parameters
return e;
}
public class Something { public int SomeVariable {get;set;} }
Again, things get tricky when dealing with optimizations and ref parameters.
I am a new developer to c# MVC3.
I have a problem that I cannot create object that contains arrays of property inside object.
For example, I want to create instance ABC.Property[] for 10 arrays.
ABC.Property[0]
ABC.Property[1]
ABC.Property[2]
.....
....
ABC.Property[10]
I used debug mode to check and found out that ABC.Property[] is null. So i cannot add the value back to that object's array.
How to crate object with propeties's array?
thank you.
namespace finance3.Models
{
public class Expected_and_Risk
{
public decimal[] Prop { get; set; }
public decimal[] Forecast { get; set; }
public string[] Name { get; set; }
public decimal[] AxB { get; set; }
public decimal[] PowAxB { get; set; }
public decimal ExpectValue(Expected_and_Risk abc)
{
decimal count = abc.Forecast.Count();
Expected_and_Risk Result = new Expected_and_Risk();
for (int i = 0 ; i < count ; i++)
{
// here is the problem
// i cannot add new data to array because it has no dimemsion and i tried this
//
// Expected_and_Risk[] Result = new Expected_and_Risk[10];
//
// but it didn't work
Result.Name[i] = abc.Name[i];
Result.Prop[i] = abc.Prop[i];
Result.Forecast[i] = abc.Forecast[i];
Result.AxB[i] = abc.Prop[i] * abc.Forecast[i];
decimal a = Result.AxB[i];
decimal sumAxB =+ a;
double temp = (double)(a * a) ;
Result.PowAxB[i] = (decimal)(temp);
}
return Convert.ToDecimal(Result);
}
}
}
You need to add a Constructor in your class and in that constructor you can define the size for your property
public class Expected_and_Risk
{
//......//your code here
public Expected_and_Risk()
{
this.Prop = new decimal[10]; // this will define an array of 10 decimal elements for Prop
}
}
Also read about object oriented programming, Also check out this article An Intro to Constructors in C#
At the moment, you've got arrays within Expected_and_Risk, but you're never initializing the variables. You could do so within a constructor:
public Expected_and_Risk(int count)
{
Name = new string[count];
...
}
... but I'd suggest that's actually a nasty design. Any time you have lots of collections, all with the same count, where x[0] corresponds to y[0] and z[0] etc, you should consider having one collection of a custom type representing the encapsulation of those properties. For example:
// Must be an int, not a decimal - you can't create an array with a decimal count
int count = abc.Forecast.Count();
// Note: rename type to follow .NET naming conventions
Expected_and_Risk[] results = new Expected_and_Risk[count];
for (int i = 0; i < count; i++)
{
results[i].Name = abc[i].Name;
...
}
... except that of course now abc would be an array too. (It's not clear whether you're really just trying to copy all the values here, or whether you've got some business logic involved. There are better ways of copying values.)
Alternatively, if you really do want collections within Expected_and_Risk, you might want to consider using List<T> instead of arrays. That way you don't need to specify the count up-front.
Better way could be to add following method into Expected_and_Risk class and call it from within constructor.
EDIT - edit is done to make Initialize private, and call it within constructor.
void Initialize(int size)
{
Prop = new decimal[size];
AxB = new decimal[size];
Forecast = new decimal[size];
PowAxB = new decimal[size];
Name = new string[size];
}
public Expected_and_Risk(int size)
{
....
Initialize(size);
}
After that use it in ExpectValue like
Expected_and_Risk Result = new Expected_and_Risk(size)// size is 10 in example;
I have the following struct defined in a user control:
public struct ColumnData
{
public string ColumnName { get; set; }
public string ColumnDataItem { get; set; }
public bool ColumnIsHyperLink { get; set; }
public string ColumnHyperLinkURL { get; set; }
public string ColumnHyperLinkPK { get; set; }
}
I create a new instance of List<ColumnData> (In a different code behind that creates an instance of the user control) and want to pass in values to it, but how do I assign them to specific attributes within the struct object?
I create an instance of the struct using the following code:
List<ColumnData> DataItems = new List<ColumnData>();
This:
List<ColumnData> DataItems = new List<ColumnData>();
creates a new list.
This:
List<ColumnData> DataItems = new List<ColumnData>();
var cd = new ColumnData();
cd.ColumnName = "Taco";
DataItems.Add(cd);
creates a new list, a new struct, and adds an item to the list.
Change that to a class; all your woes relating to modifying struct properties (etc) will go away.
Alternatively, make it an immutable struct, and initialize it with the correct values at the point of creation - then the issue is moot, no matter how many times it is subsequently copied.
IMO the first is the right approach here.
so you need to do this:
public void AddToList(ColumnData columnData)
{
DataItems.Add(columnData);
}
and call this method from your other class passing an already created and initialized columnData object.
List<ColumnData> DataItems = new List<ColumnData>();
Is creating the list that holds your structs not your structs itself.
You could use structs here for performance reasons (faster then classes).
ColumnData data = new ColumnData
{
ColumnName = "Blaa"
};
DataItems.Add(data);
I have a business class that contains many properties for various stock-exchange price types. This is a sample of the class:
public class Prices
{
public decimal Today {get; set;}
public decimal OneDay {get; set;}
public decimal SixDay {get; set;}
public decimal TenDay {get; set;}
public decimal TwelveDay {get; set;}
public decimal OneDayAdjusted {get; set;}
public decimal SixDayAdjusted {get; set;}
public decimal TenDayAdjusted {get; set;}
public decimal OneHundredDayAdjusted {get; set;}
}
I have a legacy system that supplies the prices using string ids to identify the price type.
E.g.
Today = "0D"
OneDay = "1D"
SixDay = "6D"
//..., etc.
Firstly, I load all the values to an IDictionary() collection so we have:
[KEY] VALUE
[0D] => 1.23456
[1D] => 1.23456
[6D] => 1.23456
...., etc.
Secondly, I set the properties of the Prices class using a method that takes the above collection as a parameter like so:
SetPricesValues(IDictionary<string, decimal> pricesDictionary)
{
// TODAY'S PRICE
string TODAY = "D0";
if (true == pricesDictionary.ContainsKey(TODAY))
{
this.Today = pricesDictionary[TODAY];
}
// OneDay PRICE
string ONE_DAY = "D1";
if (true == pricesDictionary.ContainsKey(ONE_DAY))
{
this.OneDay = pricesDictionary[ONE_DAY];
}
//..., ..., etc., for each other property
}
Is there a more elegant technique to set a large amount of properties?
Thanks,
j
Instead of using a string-to-decimal mapping and checking the dictionary repeatedly, use a delegate mapping/extension method:
public static class PriceConverter
{
private static readonly Dictionary<string, Action<Prices, decimal>> setters =
CreateSetterDictionary();
public static void SetPrice(this Prices p, string id, decimal newPrice)
{
Action<Prices, decimal> setter;
if (setters.TryGetValue(id, out setter))
setter(p, newPrice);
}
private static Dictionary<string, Action<Prices, decimal>>
CreateSetterDictionary()
{
var dic = new Dictionary<string, Action<Prices, decimal>>();
dic.Add("0D", (p, d) => p.Today = d);
dic.Add("1D", (p, d) => p.OneDay = d);
// etc.
return dic;
}
}
Then you can write prices.SetPrice("0D", 1.23456).
If you like, add a throw statement at the end of the SetPrice method to handle cases where the id doesn't match anything.
I would put the string variables into constants, rather than declare them every time you run the method:
private const string ONE_DAY = "D1";
If you expect the collection parameter to contain all or most of the possible values, then your code is probably cool. If you expect that the dictionary will have a small subset of the possible values, it might be more efficient to use a foreach loop and a switch statement to set values, rather then do a lookup for every possible value every time. It just depends on how many values you need to deal with and how many you get in each method call.
Define a dictionary of properties in the constructor e.g.
private Dictionary<int, PropertyInfo> propertyDictionary = new ...
MyClass()
{
this.propertyDictionary.Add(0, this.GetType().GetProperty("FirstProperty");
...
}
then access using an indexed property
decimal this[int index]
{
get
{
PropertyInfo property;
if (this.propertyDictionary.TryGetValue(index, out property))
{
// Not sure I remember the arguments right here:
property.SetValue(this, new object[] { value });
}
set
{
// Similar code
}
}
You could later on improve this code by automatically parsing the properties in the constructor using reflection,
adding all properties with an attribute that tells you what the id is.
(Instead of adding them manually in the constructor).
Just an idea:
interface IPrices_As_String{
string OD { get; set; }
// other properties here...
}
interface IPrices{
decimal Today{get; set;}
}
class Prices : IPrices, IPrices_As_String{
public decimal Today { get; set; }
public string IPrices_As_String.OD {
get { return this.Today.ToString(); }
set {
if(!String.IsNullOrEmpty(value)){
this.Today = decimal.Parse(value);
}
}
}
}
Then when I am setting the values from the legacy system, I will use the Prices class on the interface as IPrices_As_String like:
IPrices_As_String obj = new Prices();
// set values from the legacy system
IPrices obj2 = obj as IPrices; // will give me the correct object..
.
HTH.
The way I see it, you have a few options, depending on your skills, the way you are allowed to change the current POCO's or other classes:
If you must use a dictionary, create a similar dictionary which maps the "0D" etc to the OneDay names. Loop through the dictionary and assign using simple reflection.
If you can change the way the data is read, have the dictionary read with OneDay etc, instead of the "0D", which is only applicable to the external application.
Create an attribute, LegacyKeyAttribute, augment your POCO gettors/settors with this attribute. Now it becomes trivial: loop through the properties of the POCO to find the correct property for your current legacy key.
The last option requires a bit more understanding of C# than many average programmers know: writing and using attributes and reflection. However, in the end it's the cleanest and easiest solution (I'll try to come up with an example).
UPDATE: here's a little example. Meanwhile, many improvement suggestions have been posted, but none still uses attributes, while your case seems ideal. Why? It poses the least burden on existing code, I believe, and it makes reading and understanding your code even easier.
Usage:
// any price:
Prices prices = new Prices();
prices.SetPriceByLegacyName("0D", 1.2345M);
// or, your loop becomes a bit easier:
SetPricesValues(IDictionary<string, decimal> pricesDictionary)
{
foreach(string key in pricesDictionary.Keys)
{
// assuming "this" is of type Prices (you didn't specify)
this.SetPriceByLegacyName(key, pricesDictionary[key]);
}
}
The implementation:
// the simplest attribute class is enough for you:
[AttributeUsage(AttributeTargets.Property)]
public class LegacyNameAttribute : Attribute
{
public string Name { get; set; }
public LegacyNameAttribute(string name)
{
this.Name = name;
}
}
// your Prices POCO class becomes easier to read
public class Prices
{
[LegacyName("0D")] public decimal Today { get; set; }
[LegacyName("1D")] public decimal OneDay { get; set; }
[LegacyName("6D")] public decimal SixDay { get; set; }
[LegacyName("10D")] public decimal TenDay { get; set; }
[LegacyName("12D")] public decimal TwelveDay { get; set; }
[LegacyName("1DA")] public decimal OneDayAdjusted { get; set; }
[LegacyName("6DA")] public decimal SixDayAdjusted { get; set; }
[LegacyName("10DA")] public decimal TenDayAdjusted { get; set; }
[LegacyName("100DA")] public decimal OneHundredDayAdjusted { get; set; }
}
// an extension method to ease the implementation:
public static class PricesExtensions
{
public static void SetPriceByLegacyName(this Prices price, string name, decimal value)
{
if (price == null)
throw new ArgumentException("Price cannot be null");
foreach (PropertyInfo prop in price.GetType().GetProperties())
{
LegacyNameAttribute legNameAttribute = (LegacyNameAttribute)
Attribute.GetCustomAttribute(prop, typeof(LegacyNameAttribute));
// set the property if the attribute matches
if (legNameAttribute != null && legNameAttribute.Name == name)
{
prop.SetValue(price, value, null);
break; // nothing more to do
}
}
}
}
That's all there is to it. Even with all the added lines, it may well be that your total line count becomes less. But more importantly, it becomes easier to maintain and use.