C# new object but instead of copying an object, but referencing? - c#

I have a class say ClassA with a string array inside class.
In my code I have ClassA as an object, then I want to create another new ClassA object, but it should copy the original object to the new class and do whatever it is supposed to do.
But strangely, when I declare that new object, whatever changed in the new object affects the original object.
Is there any reason why I am getting such behaviour?

It sounds like you're just doing this to copy it:
ClassA obj2 = obj1;
In this case then changes to obj2 would indeed be reflected in obj1 because the objects that you're using are just pointers to the same location in the memory heap. You're not actually copying it, you're just making another reference to it.
Take a look at the ICloneable interface here. You'd want something like this:
public class ClassA : ICloneable
{
public string myString { get; set; }
public object Clone()
{
var obj = new ClassA();
obj.myString = myString;
return myObj;
}
}
Then you'd call it like this:
ClassA obj2 = (ClassA)obj1.Clone();
Keep in mind that this isn't very type-safe, however. That cast is a bit messy (and, honestly, I haven't tried it, so it might even be problematic). I don't think .NET has introduced a generic ICloneable yet. But it shouldn't be too hard to write one. Something like:
public interface ICloneable<T>
{
public T Clone();
}
public class ClassA : ICloneable<ClassA>
{
public string myString { get; set; }
public ClassA Clone()
{
var obj = new ClassA();
obj.myString = myString;
return myObj;
}
}
This should be callable like this:
ClassA obj2 = obj1.Clone<ClassA>();
or possibly even (at least with a little tweaking):
ClassA obj2 = obj1.Clone();
An additional benefit to making a generic interface like this is that any given class can be "cloneable" to other types, not just itself. You can implement as many ICloneable<T> interfaces as you want on a single class. So you could have something like:
SomeOtherClass obj3 = obj1.Clone<SomeOtherClass>();
This is all off the top of my head and I don't have a compiler handy to test it, but you get the idea.

I'm sure it is because you are just setting another reference to the one string array in the new object. If you want a separate string array you need to create a constructor that creates a new string array and copies the strings over.

You can make a constructor overload that takes a new ClassA object and copies it's parameters.
public class ClassA
{
public String SomeParam { get; set; }
public ClassA(ClassA myoldobject)
{
//Logic for initializing new object.
this.SomeParam = myoldobject.SomeParam;
}
public ClassA(String someparam)
{
this.SomeParam = someparam;
}
}
This enables you to say
ClassA one = new ClassA("Test");
ClassA two = new ClassA(one);

This is because class - is a reference type and you are trying to get the behaviour of a value type. See deeper explanation here. Also it is greatly explained in CLR via C# book by J. Richter.
If you want to copy a reference type, you might need to implement an IClonable interface and call Clone for that.

It seems that you've assigned the first object to the second ..
To copy an existed object you have to assign all of its properties values to the new object, not to assign the whole object because this way you create another reference to the same object.
To create a copy of the first instance of ClassA, try the following:
ClassA = secondObject = new ClassA();
secondObject.Property1 = firstObject.Property1;
secondObject.Property2 = firstObject.Property2;
............

Related

Make an instance of an object point to another object

What I want to do is this in effect:
this = object1
where this is the "this" keyword used within a class and object1 is the object I want "this" to point to. Is that possible?
essentially, I want
this == object1
to evaluate to true.
Edit for clarity:
Public class TestObject {
private static HashSet<string> setOfNames = new HashSet<string>();
private static List<TestObject > listOfObjects= new List<TestObject >();
private string name = null;
public TestObject (string name){
if(setOfNames.contains(name)){
foreach(TestObject o in listOfObjects){
if(o.name.equals(name)){
this = o;
break;
}
} else{
setOfNames.Add(name);
this.name = name;
listOfObjects.Add(this);
}
}
So what I want to do is if an object is ever created with the same parameters as an object before, I want the object to point to the object that was already created to avoid doing uncessary work.
No, this (no pun intended) is not possible. this cannot be reassigned (in a class).
So what I want to do is if an object is ever created with the same parameters as an object before, I want the object to point to the object that was already created to avoid doing uncessary work.
Then you need a factory that creates your instance, a dictionary that maps and caches your instances and your class should implement IEquality<T> to make the lookup and the equality comparison effective.
Edit:
A simple version (without IEquality<T>) would look like:
public class TestObject {
private static Dictionary<string, TestObject> _objectMap = new Dictionary<string, TestObject>();
public static TestObject GetInstance (string name){
if(!_objectMap.TryGetValue(name), out var instance){
instance = new TestObject(name);
_objectMap.Add(name, instance;
}
return instance;
}
private TestObject (string name){
Name = name;
}
public string Name {get;}
}
In times of DI and uncoupled services one would not use a static method, but rather have another factory class with singleton scope. And IEquality would still be useful because HashSets and Dictionaries need a good HashCodes.
Just for the record.Within a struct, this is a valid LValue, i.e. you can assign something to this in struct code . E.g.:
struct Data
{
public int Hi;
public int Lo;
public Data (Data other) {
this = other;
}
}
It's because of the copy semantics of ValueTypes, which have no object identity.
But not possible for RefTypes aka classes.

Cast array of unknowClass to array of otherClass in c#

How Can I dynamically cast at runtime.That is I am passing a child class object in the parent class object.
public abstract class tObject
{
public tObject[] someMthode(){;}
}
public class myClass : tObject
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
I want
myClass mc=new myClass();
tObject to=mc;
myClass[] mcArray=(myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
but when check any element of mcArray is correct
if (mcArray[0] is myClass)
{
//return true and run this ;
}
In fact I want cast when a method return array of tObject according to the base class :
subClass[] mcArray=(subClass[])instanceOfsubClass.someMthode()
subClass or myClass and ... are unknown class , and i don't know theirs name.
Solution
public T[] Cast<T>(tObject[] mcArray ) where T : tObject
{
if (mcArray != null)
{
int cnt = mcArray.GetLength(0);
T[] t = new T[cnt];
for (int i = 0; i < cnt; i++)
{
t[i] = (T)mcArray[i];
}
return t;
}
return null;
}
Thanks all for replies.
C# does not support that kind of array conversion. C# does -- unfortunately! -- support dangerous array covariance. That is, if you had an array myClass[] then you could implicitly convert it to an array tObject[]. This means that you can do this:
Tiger[] tigers = new Tiger[10];
Animal[] animals = tigers;
animals[0] = new Turtle();
and now we have a turtle inside an array of tigers. This crashes at runtime.
That's bad enough, but you want it to go the other way -- I have an array of animals and I'd like it to be treated as an array of tigers. That does not work in C#.
As other answers have noted, you'll need to make a second array and copy the contents of the first to the second. There are a number of helper methods to do so.
Maybe?
myClass mc = new myClass();
tObject to = mc;
//myClass[] mcArray = (myClass[])mc.someMthode();//System.InvalidCastException
//Unable to cast object of type 'tObject[]' to type 'myClass[]'
var mcArray = Array.ConvertAll(mc.someMthode(), item => (myClass) item);
Well, you can call IEnumerable.Cast for that:
var myArr = mc.someMethod().Cast<MyClass>().ToArray();
As MyClass[] implements IEnumerable<MyClass>.
EDIT: What you want is quite dangerous. Look the following code:
subClass[] mcArray=(subClass[]) new BaseClass[] {...};
If this conversion would work we could now simply make the following also:
mcArray[0] = new AnotherClass();
Now you have an array of subClasses containin one item of AnotherClass also.
If you do not know the type at compile-time you cannot expect the compiler to provide any compile-time-logic for a type it doesn´t know. Thus casting to an unknown type and calling members on isn´t supported. However you may achieve this using reflection:
var runtimeType = myArr[0].GetType();
var mi = runtimeType.GetMethod("SomeMethod");
var value = mi.Invoke(myArr[0]);
This is similar to the call
var value = ((subClass)myArr[0]).SomeMethod();
Why not solve it one step up the chain and make someMethod (spelling corrected) generic:
public abstract class tObject<T> where T:tObject
{
public T[] someMethod(){;}
}
public class myClass : tObject<myClass>
{
public string Oth0 { get; set; }
public string Oth1 { get; set; }
public string Oth2 { get; set; }
}
now myClass.someMethod returns a myclass[] and that problem is solved. However, since I'm assuming that tObject does other things that just create an array of tObjects, it may cause other problems that aren't inferrable from the code you provided.
Plus it's not 100% foolproof. There's nothing stopping you (or someone else) from defining:
public class myWeirdClass : tObject<myClass>
{
}
now myWeirdClass.someMethod also returns a myClass[], and the pattern is broken. Unfortunately there's no generic constraint that requires that the generic parameter be the defining class itself, so there's no way to prevent this flaw at compile-time.
Another option may be to move the array creation outside of the class itself, since it is a code smell in itself:
public class ObjectFactory<T> where T:tObject
{
public T[] SomeMethod()
{
... create an array of Ts
}
}

Issue with casting List<ClassA> where ClassA:Generic<Int32> to List<Generic<Int32>>

I have the next classes:
public class EntityBase<T>
{
public T Id { get; set; }
}
And it's implementers:
public class ClassA : EntityBase<Int32>
{
...
}
public class ClassB : EntityBase<Int64>
{
...
}
And in the code, which dont know about classes - ClassA and ClassB it knows only about existance of the EntityBase<...>, I do something like this:
// Here for sure I get the list of `ClassA`
object obj = GetSomeHowListOfClassA();
List<EntityBase<Int32>> listOfEntityBases = (List<EntityBase<Int32>>)obj;
And I get the error:
Unable to cast object of type 'System.Collections.Generic.List`1[...ClassA]' to type 'System.Collections.Generic.List`1[...EntityBase`1[System.Int32]]'.
I fix it like this:
var listOfEntityBases = new List<EntityBase<Int32>>(obj);
But I dont like this way, because I'm creating new List<>. Is there way to cast it?
Thx for any advance.
You can not do it for clear reason. Let's assume this line of code will work:
List<EntityBase<Int32>> listOfEntityBases = (List<EntityBase<Int32>>)obj;
This means that after that line you can do say following
listOfEntityBases.Add(new EntityBase<Int32>());
but actually this line in the same time will add EntityBase<Int32> object to your obj of type List<ClassA> - which is definitely InvalidCast.
So, you just cannot declare the same variable as List<ClassA> and List<EntityBase<Int32>> in the same time.
Though, it is easily allowed for IEnumerable<T> as you can not add new values for such collection.
And that's why they have in and out in generics declaration.
You can't do cast this way, because:
covariance in C# isn't working for classes;
interfaces IList<T> and ICollection<T> aren't covariant.
The only option you can do here (except making a copy of a list) is a casting to IEnumerabe<T>:
var listOfEntityBases = (IEnumerable<EntityBase<Int32>>)obj;

C# force inherited class looping through list

So for example I have two classes:
Class A
{
string property1;
string property2;
}
Class B : A
{
string property3;
string property4;
....
}
So B inherits class A's properties. They are sitting in a list, that is sitting in a dictionary
Dictionary <string, List<A>> myDictionary = new Dictionary<string, List<A>>();
List<A> myList = new List<A>();
There is one Dictionary, containing many List's, that all contain a mix of Class A & B objects.
While looping through, I am trying to access some properties from Class B objects, I have an if statement to find them but the program still thinks they are of type Class A and throws an error when I try and use a property3 or property4. For example:
string key = string key in dictionary;
string index = object position in list;
myDictionary[key][index].property3.someMethod();
Is there a way to tell the program that this is a class B object and allow the properties 3 & 4 to be used?
Cast the object safely as a B-type object, then check for null
var obj = myDictionary[key][index];
var bObj = obj as B;
if (bObj != null)
{
bObj.someMethod();
}
Although, I would also probably say it seems like your design is off. Ordinarily, I wouldn't expect something like this. Normally, if you're using inheritance, you'd want a design that allows them to be used interchangeably. For example, you might implement the behavior on A as a no-op, but override it on B to actually do something. This would make it so that consuming classes need not care whether the "A" thing is really an A or a B instance.

Can one copy the contents of one object to another dynamically if they have the same interface?

For example, if I have two objects, one which is of type Monkey and the other of type Dog, and they both implement IAnimal, which is something like this:
interface IAnimal
{
int numberOfEyes {get; set;}
string name {get; set;}
}
I want to do something like this:
Monkey monkey = new Monkey() { numberOfEyes = 7, name = "Henry" };
Dog dog = new Dog();
MyFancyClass.DynamicCopy(monkey, dog, typeof(IAnimal));
Debug.Assert(dog.numberOfEyes == monkey.numberOfEyes);
I imagine one can create a class like MyFancyClass using reflection... any clever person have an idea?
Thanks,
Stephen
Just to throw it in the mix... you can also use AutoMapper to map/copy one object to another.... they don't even have to implement the same interface. To make it work automagically, just the names of the properties have to match and then you just do something like:
Mapper.Map<IAnimal, MyClass>(myInstance);
A reflection based solution follows. Note that the reflection work is done only once per Type and then cached, so the overhead should be minimal. Will work with .NET 3.5 and it is not restricted to interfaces.
Note that I use reflection to get all the properties on type T and filter to the properties that have both getters and setters. I then build an expression tree for each property that retrieves the value from the source and assigns that value to the target. The expression trees are compiled and cached in a static field. When the CopyProperties method is called, it invokes the copier for each property, copying all the properties defined in type T.
// Usage
Monkey monkey = new Monkey() { numberOfEyes = 7, name = "Henry" };
Dog dog = new Dog();
DynamicCopy.CopyProperties<IAnimal>(monkey, dog);
Debug.Assert(dog.numberOfEyes == monkey.numberOfEyes);
...
// The copier
public static class DynamicCopy
{
public static void CopyProperties<T>(T source, T target)
{
Helper<T>.CopyProperties(source, target);
}
private static class Helper<T>
{
private static readonly Action<T, T>[] _copyProps = Prepare();
private static Action<T, T>[] Prepare()
{
Type type = typeof(T);
ParameterExpression source = Expression.Parameter(type, "source");
ParameterExpression target = Expression.Parameter(type, "target");
var copyProps = from prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where prop.CanRead && prop.CanWrite
let getExpr = Expression.Property(source, prop)
let setExpr = Expression.Call(target, prop.GetSetMethod(true), getExpr)
select Expression.Lambda<Action<T, T>>(setExpr, source, target).Compile();
return copyProps.ToArray();
}
public static void CopyProperties(T source, T target)
{
foreach (Action<T, T> copyProp in _copyProps)
copyProp(source, target);
}
}
}
Copy constructor is what I usually do:
class Monkey : IAnimal
{
public Monkey(IAnimal other)
{
//Copy properties here...
}
}
You have several options here:
You could go down the route of using reflection, but this will be much slower than other options, and you'll have to craft yoiur refleciton code. To make nice generic "clone" code using reflection is non-trivial, especially when you have to start catering for objects that contain lists/arrays/dictionaries of other object instances.
A copy constructor, as Dr Herbie mentioned, is one option.
Another would be to implement ICloneable on all your types (you could make you interface implement ICloneable to force all IAnimals to implement it). This may not be dynamic, like reflection (you'd have to hand craft it for each class), but assuming you just copy the property values accross, it'll be way faster than reflection.
Also worth thinking about is immutability. If you can make your concrete types immutable (using readonly on all fields so they can't be changed), then you probably don't need to worry about cloning at all. Everything can happily share the same instance safe in the knowledge that no other sharer can be modifying it in any way. This sort of immutability can be very powerful, although you need to be careful if your interface contains collections/arrays that can be modified.
Finally, if you have a lot of classes, you could look at code generation to generate C# "cloner" classes (whose job it is to generate a clone of a given type) and compile them into an assembly. You can use reflection here to create the "cloner class template", but since it generates code (that compiles with the rest of your project), you don't have the run-time hit of slow reflection.
So, there are lots of options for cloning - but using reflection, even though it can be naice and dynamic, is often not the best approach.
You could maKe IAnimal Implement ICloneable. Then do a memeberwise clone on the monkey or an other class that implements ICloneable. This is a shallow copy by the way.
public interface IAnmial : ICloneable
{
string Name{get; set;}
object Clone();
}
public class Monkey : IAnmial
{
public string Name{get; set;}
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Dog : IAnmial
{
public string Name{get; set;}
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Test()
{
public void CloneAnimal()
{
Dog dog = new Dog()
{
Name = "MyAnimal",
};
IAnimal monkey = dog.Clone() as IAnimal;
}
}
As long as DynamicCopy takes in an IAnimal as a method parameter you can do that.
But it really helps to understand what you are trying to do.
Why not just implement a method in IAnimal?
(EDIT: As commenters have helpfully pointed out, IAnimal should be converted into an abstract base class Animal for this solution. This makes sense anyway, since the whole inference behind this question is that the child classes contain properties defined in the parent.)
// In Aminal class.
public void CopyAttributes(Animal source)
{
this.numberOfEyes = source.numberOfEyes;
this.name = source.name;
}
Doing something like this via reflection gets messy quick. Should you only copy properties? What about get/set methods? What about read-only properties? That is why it is probably best to define the behavior you actually want at each level. You can then override at lower levels if desired.
// In Monkey class.
public void CopyAttributes(Monkey source)
{
super.CopyAttributes(source);
this.numberOfTails = source.numberOfTails;
}
Try looking at struct methods

Categories

Resources