I'm trying to write some code that populates a List (actually, it's a series of Lists, but we can pretend it's just one List). The idea is to add an IPackage to the List for the total quantity of IPackage on order. See the following code:
ParseExcel pe = new ParseExcel();
Pinnacle p = pe.ParsePinnacleExcel();
Rack r = new Rack(20,2,4.5,96,42,6,25*12);
foreach (PinnacleStock ps in p.StockList.Where(x =>
x.ColorCode == "10" &&
x.PackageLength == 30.64))
{
for (int i = 1; i <= ps.OnOrder; i++)
{
r.TryAddPackage((IPackage)ps);
}
}
Everything seems to be working well, insofar as the IPackage is repeatedly added to the list. However, it seems that the same instance of the object is being added, i.e. the object is not being copied each time it's added to the list.
What do I need to do to ensure that a copy of the object is inserted into the list, and not just an additional reference?
Then you need to implement ICloneable and replace
r.TryAddPackage((IPackage)ps);
with
r.TryAddPackage((IPackage)ps.Clone());
It's up to you to decide how Clone should populate the new instance of PinnacleStock that it returns.
At the most basic level, you could say
public PinnacleStock : ICloneable {
public PinnacleStock Clone() {
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone() {
return Clone();
}
// details
}
This will just do a shallow copy of PinnacleStock. Only you know if this is the correct semantics for your domain.
If you only need a shallow copy, then you can write a quick-fix clone method:
public class PinnacleStock : ICloneable
{
public PinnacleStock Clone()
{
return (PinnacleStock)this.MemberwiseClone();
}
object ICloneable.Clone()
{
return Clone();
}
// Other methods
}
If you need a deep copy (i.e. if PinnacleStock has sub-objects that you want to be copied as well), then you will need to write one yourself.
As others have said, you would need to make that copy, in some PinnacleStock-specific way:
foreach (PinnacleStock ps in p.StockList.Where(x => x.ColorCode == "10" &&
x.PackageLength == 30.64))
{
for (int i = 1; i <= ps.OnOrder; i++)
{
PinnacleStock clone = ps.CopySomehow(); // your problem
r.TryAddPackage((IPackage)clone);
}
}
However, you might want to question whether this is the right solution. Do you really need a separate instance of the PinnacleStock? Does adding a PinnacleStock to a Rack really create a new, independent instance? Are you planning to modify or track each of these individual copies separately? Is it correct that now you will have PinnacleStock instances that don't appear in your StockList? Not knowing your domain or the semantics of PinnacleStock, it's hard to be sure, but you might want to consider, say, creating a PinnacleStockRackEntry object to represent an instance of a PinnacleStock -- depends on the intended semantics of course!
You have to supply the logic to copy the object yourself. .Net does not have deep-copy built-in anywhere (with the notable potential exception of serialization). The closest it comes is the MemberwiseClone() method, but even that would copy references for any members of your type that are themselves reference type.
Related
I am attempting to iterate through the members of a list which implement a particular interface, called ImplementsGraphics and then call the method GetModels and add the return result to a list.
However, whenever I attempt to iterate through my objects, and perform the casting operation, I appear to be overwriting the same reference during my iteration. I have deduced that my problem is something to do with where, when and how I am instantiating my variables, but I can not decipher exactly what the intended behavior is.
I've tried numerous permutations of the following code:
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors.Where(n=>n is ImplementsGraphics))
{
var graphicActor = (ImplementsGraphics)actor;
models.AddRange(graphicActor.GetModels());
}
return models;
}
The problem line is var graphicActor = (ImplementsGraphics)actor; but I don't know how to write it such that declaring graphicsActor does not overwrite the existing instances of it stored in models.
Before my first several rounds of troubleshooting, I had
public List<Model> GetModels()
{
var models = new List<Model>();
foreach (Actor actor in registeredActors)
{
if((ImplementsGraphics)actor != null)
models.AddRange(((ImplementsGraphics)actor).GetModels());
}
return models;
}
Which I expected to work, as I had thought actor was safe across iteration, but apparently not.
Desired Behavior:
Return a list, which is all the return results of GetModels() for ever Actor in RegisteredActors which implements ImplementsGraphics
Actual Behavior:
Returns a list, which is the same return value repeated for each Actor in Registered Actor, which implements ImplementsGraphics.
EDIT:
In the class StaticActor which is a child of Actor and implements ImplementsGraphics its defined as follows:
public List<Model> GetModels()
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = this.Transform.WorldMatrix;
}
}
return new List<Model> { Model };
}
Additonally, I have tried two other approaches which also failed. A for loop, which itereated through all of RegisteredActors, and checked if they implemented ImplementsGraphics, explicitly calling them by their index within RegisteredActors
And a LINQ query, which went
var models = RegisteredActors.Where(n=>n is ImplementsGraphics).SelectMany(n=>((ImplementsGraphics)n).GetModels())
EDIT 2:
The deinfitions of my classes are largely irrelevant, if you want a reproducable example of the behaviour I'm having trouble with, here is a far simpler example.
class MyClass
{
MyOtherClass foo = new MyOtherClass();
int bar = 0;
MyOtherClass GetOtherClass()
{
foo.bar = bar;
return foo;
}
}
class MyOtherClass
{
int bar = 0;
}
List<MyClass> MyCollection = new List<MyClass> {new MyClass(bar = 1), new MyClass(bar = 2), new Myclass(bar = 3)};
List<MyOtherClass> MyOtherCollection = new List<MyOtherClass>();
foreach(MyClass member in MyCollection)
{
MyOtherCollection.Add(member.GetOtherClass());
}
If you were to execute the above code, I expect that the value of MyOtherCollection's bar properties would be: 1, 2, 3
However, the actual result is that:
During the first iteration the values are 1
During the second iteration the values are 2, 2
During the third iteration the values are 3, 3, 3
I would appear, since none of the provided code states, only implies, that you are attempting to reuse a reference to single Model instance to draw multiple objects. Then you are adding multiple references of the same instance to the List.
The solution may be as simple as removing the static modifier from all Model variables and/or container objects.
Normally, the solution would be to create a Deep Copy of the object when it is added to the List, however, it is not directly possible to do this in XNA *1. (not that you would want to)
It would be better to allow each Actor, or StaticActor, object to directly pass its own Model(s) through the GetModels() method in the interface implementation, instead of using the additional class MyOtherClass.
*1. XNA does not expose a public constructor for the Model class. It is possible to do this using reflection. In MonoGame, there is a public Constructor available.
I tend to split my derived Classes and subsequent Lists based on properties like "StaticCollidables","DrawableStaticCollidables" and "DrawableMovingCollidables"...
This technique may require more upfront coding(and therefore is not as "elegant"), but, it is more efficient in terms of memory overhead(8 bytes + (4(32 bit) or 8(64 bit) bytes depending on sizeof(Object)) per List) and CPU overhead(no casting or is).
If you are attempting to reuse the same model, but place it in different locations, use the DrawInstancedPrimitives method using the VertexBuffers contained within each Mesh of the model.
Please comment on which of the above solutions worked for you(if any). If I have missed something please let me know, so I can correct the answer.
I have a class with lots of properties. A shallow copy is enough to fully replicate the object.
I need to compare an object just to check if it contains exactly the same values as another.
My ideas:
The first and most obvious solution is just to create a huge method block that compares each property, one after the other.
The second would be to serialize each object and hash the file or do some sort of md5 checksum on it. (Would this actually work?)
The third is to do some sort of reflection on the object, which would automate the first option, but create an added level of complexity.
Speed isn't really an issue.
I'm interested to hear thoughts, or any other methods I am missing to do such a thing.
Edit:
Thanks all. My solution (Modified to now be recursive on generic items):
public static bool IsSame<T>(T objA, T objB)
{
var type = typeof(T);
var properties = type.GetProperties();
foreach (var pi in properties.Where(a => a.CanRead))
{
if (pi.Name == "Item")
{
var piCount = properties.FirstOrDefault(a => a.Name == "Count");
int count = -1;
if (piCount != null && piCount.PropertyType == typeof(System.Int32))
count = (int)piCount.GetValue(objA, null);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
dynamic child1 = pi.GetValue(objA, new object[] { i });
dynamic child2 = pi.GetValue(objB, new object[] { i });
return IsSame(child1, child2);
}
}
}
else
{
var val1 = type.GetProperty(pi.Name).GetValue(objA, null);
var val2 = type.GetProperty(pi.Name).GetValue(objB, null);
if (val1 != val2 && (val1 == null || !val1.Equals(val2)))
return false;
}
}
return true;
}
Most serializers are designed to ensure that data retains its integrity during serialization and deserialization, not to produce a consistent serialized format. I would avoid using serialization for this purpose.
You may consider implementing IEquatable, to have each instance capable of comparing itself with instances of the same type. Or a class do do the comparisons for you that implements IEqualityComparer. How they do this comparison may be the 'big method' that compares properties one after the other, or uses reflection.
Reflection can be a fairly quick and simple way to achieve your goal but can cause problems down the line (for example if someone adds a property to your type that should not be included for comparing equality), but obviously the converse is also true (someone adds a property that should be checked for equality, but the equality comparison isn't updated). Which approach you use should generally be decided by how comfortable the team is with each approach in tandem with the context in which the class will be used.
In your case I'd probably recommend using the reflection based approach since you wish to check the result of a shallow clone operation, so all properties should be equal.
As an aside, I'd recommend using the MemberwiseClone method to create the clone, which would lessen the need for such stringent tests.
The third option (reflection) would be the slowest, but it would also be the most robust/testable.
The hash code would be very similar to the first option, since you would have to call all of your member variables, so 1 and 2 would require you to update your .Equals(obj) and .GenerateHash() methods every time you modify your member variable lists.
Here is some code to get you started:
foreach (FieldInfo field in this.GetType().GetFields())
{
if (o[field.Name] == null)
{
if (!field.GetValue(this).Equals(o[field.Name]))
return false;
}
else
{
return false;
}
}
return true;
Another thought is that if the properties return simple value types you could group them into immutable value types of their own. For instance, if you have a customer with properties string Address1 string Address2 string City string State string Zip, you could create a value type Address that implements its own equality comparer and use that.
Not sure if this applies to your situation, but I've found that when I have a class with a lot of properties, it is often possible to do this, and it tends to make my classes simpler and easier to reason about.
If you serialize you have to specify the serialization order on each Field/Property to ensure that all data is serialized int the same order. But all you would achieve is to implement GetHashCode() in an external class.
GetHashCode() has some examples on how to override it, so look there first.
If your class has a lot of fields, and you don't want to write all the code by hand. You could use reflection to autogenerate the code. If your class changes from time to time then you could create a partial class with the GetHashCode() implementation in a T4 template.
Is there an easy way to basically just get a copy of the data instead of a reference using this method? I tried .ToArray().Where() but that still seems to pass a reference.
Example:
static void Main(string[] args)
{
List<ob> t = new List<ob>();
t.Add(new ob() { name = "hello" });
t.Add(new ob() { name = "test" });
ob item = t.Where(c => c.name == "hello").First();
// Changing the name of the item changes the original item in the list<>
item.name = "burp";
foreach (ob i in t)
{
Console.WriteLine(i.name);
}
Console.ReadLine();
}
public class ob
{
public string name;
}
You need to create a copy of your ob yourself - it's not something LINQ provides.
You could define a Clone method based on the existing protected MemberwiseClone method:
public class Item
{
public Item Clone()
{
return (Item)this.MemberwiseClone();
}
}
Then:
ob item = t.Where(c => c.name == "hello").First().Clone();
As ob is a class, it is a reference type and therefore any instance of ob, when assigned to a different variable (as is happening within the line ob item = t.Where(c => c.name == "hello").First();) will automatically copy the reference to the original instance, and not copy the actual instance itself. This is a general .NET topic regarding object copying and is separate from LINQ/Lambda,
In order to achieve what you want, you'll need to either create a Shallow Copy or a Deep Copy of the resulting instance from your LINQ projection.
For your ob class, a Shallow Copy would suffice (ShallowCopy generally copies as little as possible whereas DeepCopy copies everything - A good reference for the differences can be found here).
To perform a ShallowCopy of an object, you can use a simply MemberwiseClone which is a built-in method of .NET object type, inherited by all objects.
For something more substantial, you'll have to implement your own DeepCopy function, but that can be relatively simple. Something similar to these implementations as specified here and here.
A much easier way to go is to simply serialize your data to json and then back again. It takes a small performance hit but it is safer as it less error prone and you don't need to modify all your classes.
simply do:
var json = JsonConvert.SerializeObject(myObject)
var clone = JsonConvert.DeserializeObject<T>(json)
I need to databind multiple Lists or BindingLists (should make no difference) to one Grid. These Lists all have the same size, but different object types. The properties of the different objects in these lists should be displayed as columns next to each other, as if the first element of list A belongs to the first element of list B and so on.
Until now I copied the data into a DataTable and used this as a datasource, but for various reasons this is not possible anymore.
I know that it's not possible to bind more than one list directly, but I have no clue how to start this. I did read a bit about databinding, but it looks like I have to code a lot for this to work, work with the CurrencyManager and so on.
Is there a simple solution that could help me? Perhaps a wrapper class that does all that?
If not, could someone give me some hints which interfaces must be implemented and what else is to keep in mind?
If you cannot make these disparate objects one object, then this is not a bindable list.
You could do a shallow copy of each of these objects in a brand new object list and create them on-the-fly:
Object MyFirstObject;
Object MySecondObject;
void BindableClass( Object class_1, Object class_2 )
{
MyFirstObject = class_1;
MySecondObject = class_2;
}
public String _firstColumnString { get { return MyFirstObject.FirstColumnString; } }
public String _secondColumnString { get { return MySecondObject.SecondColumnString; } }
Better yet, pull out just the information you need in your BindableClass constructor.
void BindableClass( Object class_1, Object class_2 )
{
_firstColumnString = MyFirstObject.FirstColumnString;
_secondColumnString = MySecondObject.SecondColumnString;
}
(But now you're really just down to one list again!)
You can then create the objects by doing something like:
for (int i = 0; i < TheListSize; i++)
{
ABindableList list = new BindableClass( FirstList[i], SecondList[i] );
}
I have a List that I have populated in the main method of a console project. I pass this population to a method which is meant to take two members of the population and decompose and recombine them in a way to create two new unique members which will later be added to the population.
However when I manipulate the two original members to create the two new unique members the two original members change with in the initial population (hence altering the initial population).This means that when I go to add the new members I get duplication of entries into the List.
I'm not doing anything overly complicated I think I am just doing something stupid.
Does any one have any insight as to why this is happening ?
Here is the method that gets called to choose to initial two members of the population:
public static List<Chromosome<Gene>> runEpoch(Random rand, List<Chromosome<Gene>> population, SelectionMethod selectionMethod)
{
int populationSize = population.Count;
int selectionCount = (int)Math.Truncate((population.Count * 0.75));
if (selectionMethod == SelectionMethod.Tournament)
{
for (int i = 0; i < selectionCount; i++)
{
Chromosome<Gene> parent = selection.runTournament(rand, population);
Chromosome<Gene> parentTwo = selection.runTournament(rand, population);
//Checks for the presence of incestuous mating. In some cases incestuous mating causes a stack overflow to occur that the program can not recover from
if (parent != parentTwo)
{
//where runGeneOperators calls the crossOver method directly
offSpring = runGeneOperators(rand, parent, parentTwo);
}
else
{
i--;
}
}
}
else
{
//NSGAII
}
//fixPopulation is meant to sort and remove any excess members
return fixPopulation(rand, population, selectionMethod, populationSize); ;
}
And here is the code that is creating the two new unique members :
public List<Chromosome<Gene>> crossOver(Random rand, Chromosome<Gene> parentOne, Chromosome<Gene> parentTwo)
{
List<Chromosome<Gene>> offSpring = new List<Chromosome<Gene>>();
int crossPtOne = rand.Next(0, parentOne.Length);
int crossPtTwo = rand.Next(0, parentTwo.Length);
if ((crossPtOne == 0) && (crossPtTwo == 0))
{
offSpring.Add(parentOne);
offSpring.Add(parentTwo);
return offSpring;
}
else
{
GeneNode<Gene> fragOne = parentOne.Children[crossPtOne];
GeneNode<Gene> fragTwo = parentTwo.Children[crossPtTwo];
crossOverPoint = crossPtOne;
GeneNode<Gene> genotype = performCrossOver(parentOne.Genotype, fragTwo);
success = false;
parentOne.repair(genotype);
offSpring.Add(parentOne);
crossOverPoint = crossPtTwo;
GeneNode<Gene> genotype2 = performCrossOver(parentTwo.Genotype, fragOne);
success = false;
parentTwo.repair(genotype2);
offSpring.Add(parentTwo);
}
return offSpring;
}
private GeneNode<Gene> performCrossOver(GeneNode<Gene> tree, GeneNode<Gene> frag)
{
if (tree != null)
{
if (crossOverPoint > 0)
{
if (!success && tree.Left != null)
{
crossOverPoint--;
tree.Children[0] = performCrossOver(tree.Left, frag);
}
}
if (crossOverPoint > 0)
{
if (!success && tree.Right != null)
{
crossOverPoint--;
tree.Children[1] = performCrossOver(tree.Right, frag);
}
}
}
if (!success)
{
if (crossOverPoint == 0)
{
success = true;
return frag;
}
}
return tree;
}
In C#, objects are reference types, meaning adding something to a collection only adds a reference. If you manipulate a variable with the same reference (in your case, the "original" objects), all references pointing to that object will be changed as well. You need to copy the object somehow to have a different object and manipulate that.
To manipulate your collection and objects within it without altering it, you need to do a deep clone of the collection and it's containing objects, so you can alter list A without altering clone B. If you just wish to change some object inside the list you need to make a deep clone of the object inside the list and then alter the deep clone. This will make sure that your original is not altered.
The IClonable interface should be implemented on your objects to make them clonable.
EDIT: Per Henk's Comments, you should just implement your own copy method without implementing the IClonable interface, as per this article.
Cloning of objects comes in two forms, deep and shallow.
Shallow: This form of cloning creates a new object and then copyies the nonstatic fields of the current object to the new object. If a field is a value type, a bit-by-bit copy of the field is performed. If a field is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.
Deep:This creates a new object and clones all data members and fields of the clonable object. This object references X2 where the original will reference X.
Here a post from SO that might assist you in cloning.
Item 1 - Keep your list references private
From a API perspective, an object should never give out the reference to its internal list. This is due to the issue you have just found, whereby some other consumer code can go ahead and modify that list as it sees fit. Every reference of that list, as shared around, including the 'owning' object, has their list updated. This is usually not what was intended.
Further, the responsibility is not on the consumer to make its own copy. The responsibility is on the owner of the list to keep its version private.
It's easy enough to create a new List
private List<Gene> initialGeneList;
public List<Gene> InitialGenes
{
get { return new List<Gene>(initialGeneList); } // return a new list
}
This advice also includes passing your own list to another class/method.
Item 2 - Consider using an immutable object
Without going too much into reference vs value types, what this means is treat the object like a value type, and whenever you have an operation, return a new object instead of mutating the original.
Real value types in .net, like integers and DateTimes have the semantic of copy on assignment. e.g. When you assign, a copy is created.
Reference types can also behave like value types, and strings are good example. Many people make the following mistake, because they fail to realize the value-type semantics of System.String.
string s = "Hello World";
s.Substring(0,5); // s unchanged. still 'Hello World'
s = s.Substring(0,5); // s changed. now 'Hello'
The string method Substring() doesn't mutate the original object, but instead returns a new one containing the result of the operation.
Where appropriate, the use of immutable objects can make the program a lot easier to understand and can reduce defects considerably.
When implementing immutable objects, one caveat is the likely need to implement value equality for comparing two objects (by overriding Equals). Objects are reference types, and by default two objects are equal if their references are equal.
In this snippet, the values of the objects are equal, but they are different objects.
string s1 = "Hello";
string s2 = string.Concat("He","l", "lo");
bool equal = s1.Equals(s2);
bool referenceEqual = object.ReferenceEquals(s1, s2);
// s1 == s2 => True, Reference Equal => False
Console.Write("s1 == s2 => {0}, Reference Equal => {1}", equal, referenceEqual);