locked
How to pass an instance of a class (an object) to a method by value and not by reference? RRS feed

  • Question

  • Hi all,

    I read somewhere that when passing objects to a method, the object is passes by reference. There are no val keywords like ref or out. In VB6, there was ByRef and ByVal.

    For example, in a certain program, I want to pass a textbox object to a method that will do some operations with the textbox. But I want to pass it by value to the method so that the method doesn't have any actual effect on the original textbox. I tried assigning the main textbox to another new textbox object, like: TextBox tempTextBox = mainTextBox; But that does the same thing. I think this is because the tempTextBox is assigned a reference to the main textbox.

    So how can I use ByVal in C#? How can I pass a textbox object by value not by reference?

    Monday, January 16, 2012 2:08 PM

Answers

  • Hi,

    I fear you mixed something up! First of all there are different types: Value Types and Reference Types.

    A Value Type (e.g. Int32) directly gets some memory for the value. A Reference Value is just a reference to some memory.

    And then you have parameters. Paranmeters can be by value or by reference. Both is available in C# and VB. VB has the ByVal / ByRef keywords. C# has the keywords ref and out (Without any keyword, the parameter is passed by value - out is like ref but the compiler do not want you to initialize the variable first).

    But when you have a value parameter:
    - for a value type, the value is given to the method:
    - for a reference type, the reference is given to the method. (So you can change the referenced object but not the reference!)

    And with a reference parameter:
    - for a value type, a reference to the value is given to the method.
    - for a reference type, a reference to the reference is given to the method.

    With kind regards,

    Konrad

    • Proposed as answer by JollyWagoner Monday, January 16, 2012 3:27 PM
    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:26 PM
    Monday, January 16, 2012 2:18 PM
  • IClonable

    The proper way would be to implement ICloneable on your object (where you might use the object.MemberwiseClone method). But IClonable has some serious issues: It doesn't specify whether it should perform a deep or a shallow copy; It doesn't provide a proper way to handle inheritance. 

    See: http://www.windojitsu.com/blog/copyctorvsicloneable.html

    Copy Constructor

    .NET doesn't have built in support for copy constructors, the same way C++ has. You can write your own copy constructor. See the following article on how to do it.

    See: http://msdn.microsoft.com/en-us/library/ms173116(v=vs.80).aspx

    Serialization 

    I want to object against serialization. First, many types (including TextBox for that matter) don't support serialization. Second, it's darn slow. Third it's very brittle with regards to inheritance, unless you seriously invest in ISerializable implementations. 

    AutoMapper

    There are a number of automated mapping tools available, these can be used to create a behavior similar to MemberWiseClone, but also much more specific implementations are possible.

    See: https://github.com/AutoMapper/AutoMapper

    One missed so far: Roll your own

    As you're probably the only person using the interface, you can create your own version of IClonable that doesn't have the issues related to the standard ICloneable interface. You could clearly specify what kind of cloning would take place and you're in total control on how inheritance is handled.


    My blog: blog.jessehouwing.nl
    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:34 PM
    Tuesday, January 17, 2012 8:00 PM
  • Keep in mind all of this is really only applicable to classes that you're writing, not for existing classes.  They need to already have this functionality in place, and TextBox doesn't.

    Other options are simply to manually copy all of the data from one object to another.  For something like a List (or other data structure) you would make a new collection, go through every item in the original collection, and then add that item to the new collection.  Depending on your requirements, you may or may not want to make a deep copy of every item in that collection.

    Textboxes, on the other hand, have quite a lot of different kinds of information, much of which you don't have access to modify.  For more 'transparent' classes you can simply make a new object and copy over each property, but that likely won't work in your case.

     

    Now back to my previous post.  I asked you if you could describe what information you need to access from your textbox, or better yet what you are more generally trying to do that involves needing a copy of the textbox in the first place so that we could actually help you solve your underlying problem, because getting a 'copy' of an actual textbox object is unlikely to happen (at the very least it wouldn't be trivial).

    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:23 PM
    Wednesday, January 18, 2012 2:55 PM

All replies

  • Hi,

    I fear you mixed something up! First of all there are different types: Value Types and Reference Types.

    A Value Type (e.g. Int32) directly gets some memory for the value. A Reference Value is just a reference to some memory.

    And then you have parameters. Paranmeters can be by value or by reference. Both is available in C# and VB. VB has the ByVal / ByRef keywords. C# has the keywords ref and out (Without any keyword, the parameter is passed by value - out is like ref but the compiler do not want you to initialize the variable first).

    But when you have a value parameter:
    - for a value type, the value is given to the method:
    - for a reference type, the reference is given to the method. (So you can change the referenced object but not the reference!)

    And with a reference parameter:
    - for a value type, a reference to the value is given to the method.
    - for a reference type, a reference to the reference is given to the method.

    With kind regards,

    Konrad

    • Proposed as answer by JollyWagoner Monday, January 16, 2012 3:27 PM
    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:26 PM
    Monday, January 16, 2012 2:18 PM
  • Konrad has describe the general concepts at issue here.

    For your specific example, TextBox is a class, which is a reference type.  Since you aren't using the 'ref' or 'out' keywords, you are passing the variable by value.  That said, the variable that you are passing is itself a reference.  

    If you describe in more detail what you're trying to do, we might be able to provide more options for you in this specific instance.  Some possibilities are:

    • just pass the data that you need, i.e. the text, rather than the whole object
    • Create a new object that holds the data you want to pass; give the object the textbox in it's constructor and have methods/properties for the data you want to expose.  Have all of the properties have a getter (that gets the data from the textbox) but no setter.  If you prefer methods, have get methods to get the data that you want and no set methods.  This would expose the data without allowing the textbox to be modified.
    • Proposed as answer by Anil Sachin Tuesday, January 17, 2012 1:36 PM
    Monday, January 16, 2012 3:46 PM
  • Ok Konrad and Servy,

    I now fully understand that I just cannot pass a COPY of an object (eg a TextBox object) to a method. If I want, then I've to use structs because structs are value types. But I can still treat structs as classes just by adding a ref keyword before the struct parameter.

    Now can you please make me understand how to create identical objects so that it totally new. For example:

    // I don't want this
    MyClass obj1 = new MyClass();
    MyClass obj2 = obj1; // this just assigns the reference. i.e the actual data is not copied and memory is saved.
    
    // I want this:
    MyClass obj1 = new MyClass();
    MyClass obj2 = the actual data of obj1, not the referene to obj1;
    


    I'm now busy with some other tasks, so I'll not be working with C# for 3/4 days. I'll try to check this forum and I'll wait for your posts. I'll try to posts updates if I can.

    Thanks

    Tuesday, January 17, 2012 10:35 AM
  • There are several options for copying objects like

    - Impelement ICloneable interface

    - Create copy constructor

    - Use serialization

    You can find multiple solutions via Google. See for example http://stackoverflow.com/questions/78536/cloning-objects-in-c-sharp


    • Edited by MasaSam Tuesday, January 17, 2012 12:58 PM
    Tuesday, January 17, 2012 12:57 PM
  • IClonable

    The proper way would be to implement ICloneable on your object (where you might use the object.MemberwiseClone method). But IClonable has some serious issues: It doesn't specify whether it should perform a deep or a shallow copy; It doesn't provide a proper way to handle inheritance. 

    See: http://www.windojitsu.com/blog/copyctorvsicloneable.html

    Copy Constructor

    .NET doesn't have built in support for copy constructors, the same way C++ has. You can write your own copy constructor. See the following article on how to do it.

    See: http://msdn.microsoft.com/en-us/library/ms173116(v=vs.80).aspx

    Serialization 

    I want to object against serialization. First, many types (including TextBox for that matter) don't support serialization. Second, it's darn slow. Third it's very brittle with regards to inheritance, unless you seriously invest in ISerializable implementations. 

    AutoMapper

    There are a number of automated mapping tools available, these can be used to create a behavior similar to MemberWiseClone, but also much more specific implementations are possible.

    See: https://github.com/AutoMapper/AutoMapper

    One missed so far: Roll your own

    As you're probably the only person using the interface, you can create your own version of IClonable that doesn't have the issues related to the standard ICloneable interface. You could clearly specify what kind of cloning would take place and you're in total control on how inheritance is handled.


    My blog: blog.jessehouwing.nl
    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:34 PM
    Tuesday, January 17, 2012 8:00 PM
  • Keep in mind all of this is really only applicable to classes that you're writing, not for existing classes.  They need to already have this functionality in place, and TextBox doesn't.

    Other options are simply to manually copy all of the data from one object to another.  For something like a List (or other data structure) you would make a new collection, go through every item in the original collection, and then add that item to the new collection.  Depending on your requirements, you may or may not want to make a deep copy of every item in that collection.

    Textboxes, on the other hand, have quite a lot of different kinds of information, much of which you don't have access to modify.  For more 'transparent' classes you can simply make a new object and copy over each property, but that likely won't work in your case.

     

    Now back to my previous post.  I asked you if you could describe what information you need to access from your textbox, or better yet what you are more generally trying to do that involves needing a copy of the textbox in the first place so that we could actually help you solve your underlying problem, because getting a 'copy' of an actual textbox object is unlikely to happen (at the very least it wouldn't be trivial).

    • Marked as answer by ddlyProgrammer Thursday, January 19, 2012 12:23 PM
    Wednesday, January 18, 2012 2:55 PM
  • Servy,

    I was just looking for a way that I can use to pass objects to a method by value. From all of the replies in this thread, I realized that there are no such straightforward way. From all of the methods above, I liked the "Copy Constructor" method the best.

    And the thing I'm trying to do is complex enough that it cannot be posted on this form. I just gave the TextBox class as an example. The main thing is quite complex. By the way, the problem has been solved.

    Thanks to you all for your replies.

    Thursday, January 19, 2012 12:35 PM