JDYoder Posted May 20, 2005 Posted May 20, 2005 I have an object I want to clone. I know the type, so I can declare my new object as the type I want, but then I want to loop through all the properties and assign them from the old variable to the new one. Is this possible? Quote
thenerd Posted May 20, 2005 Posted May 20, 2005 Would dim otherobject as whatever otherobject = new whatever otherobject.randomproperty = 532 otherobject.what = "poo" dim newobject as whatever Newobject = otherobject work? Quote
Jaco Posted May 21, 2005 Posted May 21, 2005 Uh.. now you have two variables pointing to the same object, not an original plus a clone. You either have to copy all the properties or even better use serialization. You can serialize to a memory stream and then de-serialize back to the new object. The problem with copying all the properties is that: 1. It's tedious and must be modified when the properties change 2. You have to remember to do the copying from the class that the object is instantiated from - otherwise you'll miss the private fields that have no accessor (i.e., the hidden internal object state). Quote
thenerd Posted May 21, 2005 Posted May 21, 2005 Wow, you're right, It doesn't work. I'm sorry, I'll test my ideas before posting them for now on. So basically, you want a sub in the class that will do this? Public Class whatever Public something As Integer Public what As String Public Sub clone(ByRef hmm As whatever) 'make sure it's byref. hmm = New whatever hmm.what = what 'set all the properties to eachother hmm.something = something End Sub End Class Quote
Jaco Posted May 21, 2005 Posted May 21, 2005 Here's a more maintainable way to do it: 1. just set the Serializable attribute on the class you want to copy e.g., <Serializable()> _ Public Class ClassYouWantToCopy 2. place this general purpose routine somewhere (anywhere) and call it when you have a serializable class object you want a clone of: Public Function CloneObject(ByVal oObject As Object) As Object 'returns a separate object with all serializable 'properties set to those of oObject (the object class 'must have the "Serializable" attribute) Dim oStream As New System.IO.MemoryStream() Dim oFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter() oFormatter.Serialize(oStream, oObject) oStream.Seek(0, IO.SeekOrigin.Begin) Return oFormatter.Deserialize(oStream) End Function If you don't have control of the class for the object you want to clone (i.e., you can't set it to 'Serializable'), then you'll have to set each property one by one, but as I mentioned in the other reply, you can't guarantee a proper clone unless the clonable class is doing the copying (to include private fields). Quote
JDYoder Posted May 21, 2005 Author Posted May 21, 2005 Since objects change, and I don't want to have to remember to change my clone object by setting dozens of properties one by one, (and since I don't have access to the object's class) I was hoping VB.NET could do something like... [o1 of class "whatever" already exists] Dim i as integer Dim o2 as new whatever For i = 0 to whatever.properties.count - 1 o2(i).property = o1(i).property next i That way, I'd always get a perfect clone, regardless if the object changes down the road. FYI, I had someone write me this later in the day... Use Reflection and GetProperties(). Here's the MS KB article and their code sample... http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemtypeclassgetpropertiestopic.asp I haven't played with it yet, but it looks promising. Pretty slick stuff if it works as I'm hoping, since I'd be able to make general "Clone code" that would work for any object. I can't play with it until Monday when I get back to work, but anyone's welcome to look at it sooner than I can and report your findings. So is Serializing similiar to this or not? (I'm not familiar with the term and am unclear what it's all about.) Quote
Jaco Posted May 21, 2005 Posted May 21, 2005 I think it comes down to this: if the classes in question come under your control (i.e., you can ensure they are serializable), then my approach is by far the easiest - the code I posted is all you need. However, for objects of classes you can't be sure are serializable, then you need another approach. Quote
Administrators PlausiblyDamp Posted May 21, 2005 Administrators Posted May 21, 2005 You need to investigate reflection if you want to do this with objects that aren't under your control. Clicky for an example. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
IngisKahn Posted May 23, 2005 Posted May 23, 2005 (edited) And be sure to use the ICloneable interface. Also have you checked out MemberwiseClone? Edited May 23, 2005 by IngisKahn Quote "Who is John Galt?"
JDYoder Posted May 23, 2005 Author Posted May 23, 2005 And be sure to use the ICloneable interface. Also have you checked out MemberwiseClone? To your first statement, "Why is that?" And to your second one, no I haven't -- what is it? Quote
IngisKahn Posted May 23, 2005 Posted May 23, 2005 ICloneable is a standard CLR interface which all classes that support cloning should implement. MemberwiseClone is a private member function of Object that does exactly what you're trying to do (i.e. perform a shallow copy). If an object doesn't implement ICloneable then it's probably not ment to be copied. MSDN is your friend :) Quote "Who is John Galt?"
NeuralJack Posted September 12, 2006 Posted September 12, 2006 This is an ancient thread but I was wondering something. Is there an explicit way for me to designate which way i use the '=' operator each time i use it? in.. subject = predicate It appears that '=' will make a copy of the predicate if the predicate and subject are simple properties or values. I dont like that the same operator doesnt make copies when the subject and predicate are objects. Essentially it's just passing the predicate reference to the subject. I'd just like a different operator for two very different operations. Let me know if one exists. Confusion could result with this operator, from what I see. Lets say : dim x as integer = 5 dim y as integer = 10 x = y y = 20 Does x now equal 20? havent tested but I dont think so. Or: Button1.text = Button2.text Button2.text = "Hello Sucker" Does Button1.text = "Hello Sucker" now? havent tested but i dont think so. I need to make an exact COPY of another button. The best thing i could do is use MemberwiseClone but it doesnt seem to be an option. I'll make a custom subroutine if I cant do it an easier way. This does not work: button1 = button2.MemberwiseClone Quote Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Leaders snarfblam Posted September 12, 2006 Leaders Posted September 12, 2006 To answer your first question (the use of the = operator): Of course, X will not = 20. You need to understand how assignment works with value types and reference types--the behavior of = is, in fact, already explicitly defined. If you look at it from the right prespective, they actually work the same way. First, examine the way that normal (value-type) variable assignment works. When you say SomeVariable = SomeValue, you have a spot in memory referenced by SomeVariable and the value, SomeValue, is copied into that spot in memory. Let's look at a play-by-play: '--------------------------X----Y dim x as integer = 5 ' [u]5[/u] 0 The value of 5 is copied to x dim y as integer = 10 ' 5 [u]10[/u] The value of 10 is copied to y x = y ' [u]10[/u] 10 The value of Y (10) is copied to x y = 20 ' 10 [u]20[/u] The value is 20 is copied to Y (but not to X) Now we look at reference types. If you have any experience at all with C# or ASM, you will be familiar with pointers. A pointer is just a 32-bit integer (in Win32) that references a memory location. Pointers are at the heart of .Net reference types. A variable that is declared as a reference type actually only stores a pointer. When you call a method or set a field or property, you tell the compiler "Perform this operation on the object stored at the memory location specified by my variable." For example, the code MyObject.SomeFunction() compiles down to "Call SomeFunction on the object that the pointer in MyObject points to." The signifigance of that is that you must understand that reference-type variables are just pointers, internally represented exactly like an integer. So, when you assign an object to a variable, the reference (i.e. the pointer) is being assigned. Let's have a look. 'Class that holds a single value Class SampleClass Public Value As Integer 'Create instance with specified value Public Sub New(val As Integer) Value = val End Sub End Class 'Now, let's examine how assignment works here. 'These memory locations are random, picked out of a hat, just to demonstrate. Sub ShowAssignment() 'MemoryLocation----------------X----------------Y--------------------- 'Value-----------------------------------X--------------Y------------- Dim X As New SampleClass(5) '[u]123456[/u] [u]5[/u] 0 (Nothing) Dim Y As New SampleClass(10) '123456 5 [u]90210[/u] [u]10[/u] X.Value = Y.Value '123456 [u]10[/u] 90210 10 Y.Value = 20 '123456 10 90210 [u]20[/u] ' So far the values seem to be exactly the same as before. ' Here's where things get different: ' We will assign the pointer of Y to X X = Y '[u]90210 20[/u] 90210 20 ' X now points to a different location in memory than before: the ' same location as Y. Now a change in Y will be reflected in X, and ' vice-versa X.Value = 100 '90210 [u]100[/u] 90210 [u]100[/u] ' Notice that because X and Y point to the same memory, their value ' WILL ALWAYS be the same. End Sub The confusion comes from the fact that .Net does a real good job of hiding your pointers from you. If you get a good grasp on how pointers work, though, you will have a good understanding of how and why reference types behave the way they do. To answer your question about making an exact copy of a button: This is not nearly as simple as it seems. If you create a member-by-member clone ("shallow copy") of a button you will run into problems, and fast. Button objects are full of pointers. If you create a member-by-member clone of a .Net Button object you will copy all the pointers instead of the data that the pointers reference (copying all the data that the pointers point to would be a "deep copy"). This means that you will have two objects that .Net thinks are separate buttons, but they will both reference the same Windows resources (i.e. Windows will think that they are the same button while .Net thinks they are different). If you assign one Button variable to another it will just copy .Net's pointer, so both .Net and Windows will treat it as the same object. If you want to create a duplicate of a Button you will have to write your own function to do so. It will have to create a new button and then copy all of the properties over. Quote [sIGPIC]e[/sIGPIC]
NeuralJack Posted September 12, 2006 Posted September 12, 2006 Thanks MarbleEater, that was very informative. I really should hit a .Net textbook here one day and go over some basics. I have actually used the '=' operator before for passing button Pointers and it's very useful. I wanted a lazy way to copy a button but it makes sense that would be slightly more difficult. So I made my own copy function that copies the properties that I think are important. It would be nice to know exactly what are reference type pointers and what are not but I guess all data type instances will not be pointers. All other classes, objects, controls, will be pointers. Quote Currently Using: Visual Basic.Net 2005, .Net Framework 2.0
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.