Hi Philipp,
In this case, the result would always be the original o instance, never
o2.
Not following you 100% on this one, but it looks like what you are trying to
do is pass in an object and then let the user modify the object, they can
then back out of the changes or commit the changes. In C# parameters are
passed by value, even though the underlying type could be passed by reference
i.e.
Given a Person class, this is a reference type since it is not inheriting
from System.ValueType:
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public string Name
{
get
{
return this.name;
}
}
}
If we create an instance of a person, and pass it to a function without
using the ref keyword the person instance is passed by reference (i.e. inside
the function the parameter is refering to the same instance of the object
that was passed into the function) but we cannot change what the reference
outside the function is pointing to since the parameter itself was copied
when the function was called:
class Person
{
private string name;
public Person(string name)
{
this.name = name;
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person("frank");
ChangePersonName1(p1);
//Now p1.Name == "bob"
ChangePersonName2(p1);
//Still p1.Name == "bob"
ChangePersonName3(ref p1);
//Here p1.Name == "john"
Console.ReadLine();
}
static void ChangePersonName1(Person person)
{
person.Name = "bob";
}
static void ChangePersonName2(Person person)
{
//the person parameter is a copy of the
//frank variable so if we change what the
//person variable points to we are not
//changing what the frank variable points to.
person = new Person("mark");
//here person.Name == "mark" but still p1.name == "bob"
}
static void ChangePersonName3(ref Person person)
{
//here the person variable and p1 variable are the same
//variable so changing what person refers to will change
//what p1 refers to.
person = new Person("john");
//here person.Name == "john" and p1.Name == "john"
}
I personally do not like to use the ref keyword since it can make code
confusing and not easy to follow. Instead of the code you have:
public static bool EditMyObject(ref MyObject o)
{
MyObject o2 = o.Clone();
if (...) {
o = ...
} else { // return backup copy
o = o2;
}
}
I would do something like:
public static MyObject EditMyObject(MyObject o)
{
MyObject o2 = o.Clone();
//let user modify o2 instance.
showGUI(o2);
if (userWantsToAcceptChanges)
{
return o2;
}
else
{ // return backup copy
return o;
}
}
You don't need a bool to indicate success or not (if something goes wrong
you can throw an exception), then the calling code would be something like:
MyObject myObj = new MyObject();
myObj = EditMyObject(myObj);
Also an inportant point to remember is that if you cloning an object like in
your example, you will need to make a deep copy if you are exposing any of
the properties of a object being referenced by the o2 instance, otherwise a
user could modify these references and then click cancel at which point you
would return the o instance which would be unchanged but the items references
by it could still have been modified. For value types, i.e. types deriving
from System.ValueType the object when passed to a method is shallow copied
unlike reference types, for more info, see:
http://www.yoda.arachsys.com/csharp/parameters.html
Personally when I create a GUI I normally use the Command design pattern
which gives the added benefit of allowing undo/redo and helps increase the
testability of your GUI code through unit tests.
HTH
Mark.
--
http://www.markdawson.org
Philipp Reif said:
Hi all,
I've got a little hole in my head concerning references. Here's what
I'm trying to do: I'm calling a function, passing the reference of a
business object for editing. The function clones the object, calls an
editor dialog to let the user edit the object, and then - depending on
the DialogResult - assigns either the clone/backup copy or the modified
object itself to the reference. Maybe I'm thinking too much in pointer
references - but isn't it possible to alter a reference (not the
referenced object) like this:
public static bool EditMyObject(ref MyObject o)
{
MyObject o2 = o.Clone();
if (...) {
o = ...
} else { // return backup copy
o = o2;
}
}
In this case, the result would always be the original o instance, never
o2.
Please, untie the knot in my brain ;-) - thank you in advance,
Phil