24

In C#, I know that by default, any parameters passed into a function would be by copy, that's, within the function, there is a local copy of the parameter. But, what about when an object is passed as parameter to another class?

Would a scenario like the following one be passed by reference or by value:

class MyClass {
   private Object localObj;

   public void SetObject(Object obj) {
      localObj = obj;
   }
}

void Main() {
   Object someTestObj = new Object();
   someTestObj.name = "My Name";
   MyClass cls = New MyClass();
   cls.SetObject(someTesetObj);
}

In this case, would the class variable localObj be having the same copy as the someTestObj created in the Main driver class? Or would the two variables be pointing to a different object instance?

Carven
  • 14,988
  • 29
  • 118
  • 161
  • 6
    "In C#, I know that by default, any parameters passed into a function would be by copy", other way around. Only struct passed to a function get copied in the scope of the function. Objects are always by reference, meaning there is only one version in memory, and every variable point toward it. – LightStriker Oct 21 '12 at 12:13

7 Answers7

23

"Objects" are NEVER passed in C# -- "objects" are not values in the language. The only types in the language are primitive types, struct types, etc. and reference types. No "object types".

The types Object, MyClass, etc. are reference types. Their values are "references" -- pointers to objects. Objects can only be manipulated through references -- when you do new on them, you get a reference, the . operator operates on a reference; etc. There is no way to get a variable whose value "is" an object, because there are no object types.

All types, including reference types, can be passed by value or by reference. A parameter is passed by reference if it has a keyword like ref or out. The SetObject method's obj parameter (which is of a reference type) does not have such a keyword, so it is passed by value -- the reference is passed by value.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • What? Wrong, the last line doesn't make sense. Objects are always passed by reference (period). – States Nov 11 '12 at 20:30
  • 7
    @States: No, "objects" are not values in C#, and cannot be "passed". – newacct Nov 12 '12 at 07:28
  • 1
    Isn't an instance of a `struct` an object? These are passed by value – Andrew Skirrow Jul 11 '19 at 14:49
  • Yes structs are value types objects are reference types. Simple as that. If you'd like to know more about when each is appropriate there are a great many articles on the topic out there this one from Microsoft Docs is a good example. https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct – Hawkeye4040 Feb 04 '20 at 11:09
12

Objects will be passed by reference irrespective of within methods of same class or another class. Here is a modified version of same sample code to help you understand. The value will be changed to 'xyz.'

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class Employee
    {
        public string Name { get; set; }
    }

    public class MyClass
    {
        public Employee EmpObj;

        public void SetObject(Employee obj)
        {
            EmpObj = obj;
        }
    }

    public class Program
    {
       static void Main(string[] args)
        {
            Employee someTestObj = new Employee();
            someTestObj.Name = "ABC";

            MyClass cls = new MyClass();
            cls.SetObject(someTestObj);

            Console.WriteLine("Changing Emp Name To xyz");
            someTestObj.Name = "xyz";

            Console.WriteLine("Accessing Assigned Emp Name");
            Console.WriteLine(cls.EmpObj.Name); 

           Console.ReadLine();
       }       
    }
 }
Daniel Ormeño
  • 2,743
  • 2
  • 25
  • 30
Rajee
  • 272
  • 2
  • 8
  • 24
    Objects aren't passed by reference. References are passed by value. That's a *big* difference, and it's important to be clear about it, IMOI. – Jon Skeet Jul 04 '15 at 21:15
  • 1
    By default Objects are passed by value not by reference, to pass object by reference we use (ref object) – Ashraf Alshahawy Dec 15 '16 at 12:13
6

I found the other examples unclear, so I did my own test which confirmed that a class instance is passed by reference and as such actions done to the class will affect the source instance.

In other words, my Increment method modifies its parameter myClass everytime its called.

class Program
{
    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        Console.WriteLine(myClass.Value);  // Displays 1
        Increment(myClass);
        Console.WriteLine(myClass.Value);  // Displays 2
        Increment(myClass);
        Console.WriteLine(myClass.Value);  // Displays 3           
        Increment(myClass);
        Console.WriteLine(myClass.Value);  // Displays 4
        Console.WriteLine("Hit Enter to exit.");
        Console.ReadLine();
    }

    public static void Increment(MyClass myClassRef)
    {
        myClassRef.Value++;
    }
}

public class MyClass
{
    public int Value {get;set;}
    public MyClass()
    {
        Value = 1;
    }
}
RitchieD
  • 1,831
  • 22
  • 21
5

Assuming someTestObj is a class and not a struct, the object is passed by reference, which means that both obj and someTestObj refer to the same object. E.g. changing name in one will change it in the other. However, unlike if you passed it using the ref keyword, setting obj = somethingElse will not change someTestObj.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
2

An Object if passed as a value type then changes made to the members of the object inside the method are impacted outside the method also. But if the object itself is set to another object or reinitialized then it will not be reflected outside the method. So i would say object as a whole is passed as Valuetype only but object members are still reference type.

private void button1_Click(object sender, EventArgs e)
{
    Class1 objc ;
    objc = new Class1();
    objc.empName = "name1";
    checkobj(objc);
    MessageBox.Show(objc.empName);  //propert value changed; but object itself did not change
}

private void checkobj (Class1 objc)
{
    objc.empName = "name 2";
    Class1 objD = new Class1();
    objD.empName ="name 3";
    objc = objD ;
    MessageBox.Show(objc.empName);  //name 3
}
sjd
  • 1,329
  • 4
  • 28
  • 48
0

If you need to copy object please refer to object cloning, because objects are passed by reference, which is good for performance by the way, object creation is expensive.

Here is article to refer to: Deep cloning objects

Community
  • 1
  • 1
Farfarak
  • 1,497
  • 1
  • 8
  • 8
0

In general, an "object" is an instance of a class, which is an "image"/"fingerprint" of a class created in memory (via New keyword).
The variable of object type refers to this memory location, that is, it essentially contains the address in memory.
So a parameter of object type passes a reference/"link" to an object, not a copy of the whole object.