ghiboz
ghiboz

Reputation: 8003

Pass class instance without reference

I've this question about pass some instances by ref or not: here is my problem:

Case 1: simple var like int:

private void button2_Click(object sender, EventArgs e)
{
    int nTest = 10;

    testInt(nTest);
    MessageBox.Show(nTest.ToString());
    // this message show me 10

    testIntRef(ref nTest);
    MessageBox.Show(nTest.ToString());
    // this message show me 11
}

private void testInt(int nn)
{
    nn++;
}

private void testIntRef(ref int nn)
{
    nn++;
}

this is exactly what I think, if I use the ref, the parameter is passed by reference, so if is changed, when I exit from the function, the value is changed...

Case 2: class:

// simple class to understand the reference..
public class cTest
{
    int nTest;
    public cTest()
    {
        setTest(0);
    }

    public void setTest(int n)
    {
        nTest = n;
    }

    public int getTest()
    {
        return nTest;
    }
}

// my main code
private void button3_Click(object sender, EventArgs e)
{
    cTest tt = new cTest();
    tt.setTest(2);

    testClass(tt);

    // I expect that the message shows me 2, 'cause testClass
    // doesn't have (ref cTest test)
    MessageBox.Show(tt.getTest().ToString());
}

private void testClass(cTest test)
{
    test.setTest(55);
}

and, as written in the comment on the code, I don't have passed my cTest as reference, but the result is the same, the message show me 55 and not 2..

How can I pass a class without reference?

Upvotes: 6

Views: 20785

Answers (3)

Sven Vranckx
Sven Vranckx

Reputation: 424

If you just want to make sure that a method can't modify an argument, then you can create a read-only base class:

public abstract class ReadOnlyUser
{
    public string GetName() { ... }
}

public class User : ReadOnlyUser
{
    public void SetName(string name) { ... }
}

Then you can write the method in such a way that the method body can't modify the argument by mistake:

public void Register(ReadOnlyUser user)
{
    string name = user.GetName();
    user.SetName("John"); // doesn't compile
}

Of course you can invoke this method with an instance of the User class:

var user = new User(...);
Register(user);

You can also implement a read-only interface:

public interface IReadOnlyUser
{
    string GetName();
}

public interface IUser : IReadOnlyUser
{
    void SetName(string name);
}

public class User : IUser
{
    public string GetName() { ... }
    public void SetName(string name) { ... }
}

public void Register(IReadOnlyUser user)
{
    string name = user.GetName();
    user.SetName("John"); // doesn't compile
}

Upvotes: 0

gdoron
gdoron

Reputation: 150253

How can I pass a class without reference?

You can't.

You can clone that instance and send it, but it will still be sent by ref...

  • class - Reference type
  • struct - Value type.

Reading:

Quoting Jon Skeet C# in depth second edition:

MYTH #3: “OBJECTS ARE PASSED BY REFERENCE IN C# BY DEFAULT”

This is probably the most widely propagated myth. Again, the people who make this claim often (though not always) know how C# actually behaves, but they don’t know what “pass by reference” really means. Unfortunately, this is confusing for people who do know what it means. The formal definition of pass by reference is relatively complicated, involving l-values and similar computer science terminology, but the important thing is that if you pass a variable by reference, the method you’re calling can change the value of the caller’s variable by changing its parameter value. Now remember that the value of a reference type variable is the reference, not the object itself. You can change the contents of the object that a parameter refers to without the parameter itself being passed by reference. For instance, the following method changes the contents of the StringBuilder object in question, but the caller’s expression will still refer to the same object as before:

void AppendHello(StringBuilder builder)
{
    builder.Append("hello");
}

When this method is called, the parameter value (a reference to a StringBuilder) is passed by value. If I were to change the value of the builder variable within the method—for example, with the statement builder = null;—that change wouldn’t be seen by the caller, contrary to the myth.

C# in depth Value types and reference types page 46

Upvotes: 14

justin.lovell
justin.lovell

Reputation: 675

If you want something like that, you want to use struts instead of classes.

Upvotes: 4

Related Questions