RE: Observation on object references
- From: Shailen Sukul <shane@xxxxxxxxxxxxx>
- Date: Tue, 14 Nov 2006 17:51:01 -0800
yes you are right.
I was *hoping* that the data variable would get updated to "Handler2" but
what I forgot that o.args.data is a referemce type and re-assigning it does
not guarantee that whatever is pointing to it will get updated. o.args.data
just gets re-pointed to a new memory location and data is still pointing at
the old memory location.
Wouldn't it be nice if we could declare a reference type in C# that would
get updated along with its referenced variable.
so data --> args.data
args.data gets a new reference
data --> new reference
(sigh)
--
Good luck!
Shailen Sukul
Architect
(BSc MCTS, MCSD.Net MCSD MCAD)
Ashlen Consulting Service P/L
(http://www.ashlen.net.au)
"Mark R. Dawson" wrote:
Hi Shailen,.
if you run your code you get the following output o the command line:
args.data.field1: Handler2
data.field1: Handler1
To me that seems exactly what I would expect. Basically you Orchestrator
object o initially creates a Data object data (we will call this d1) and
passes in the reference to that to the args variable, at this point we know:
o.args.data.field1 == "null", where data refers to d1 instance.
You then call processs and pass in the args variable, Handler1 changes the
field1 value so:
o.args.data.field1 == "Handler1"
everything is good so far, the args instance is passed to Handler2, at this
point Handler2 creates a new instance of the Data object (call this d2) and
passes that to the args object, so before we had:
o.args.data -> referring to d1 instance we created earlier.
now we have o.args.data -> refers to d2, and set the field value
o.args.data.field1 == "handler2"
so back in the following code:
public void Start()
{
args = new HandlerArgs(data);
h1.successor = h2;
h1.Process(args);
Console.WriteLine(string.Format("args.data.field1:
{0}",args.data.field1));
Console.WriteLine(string.Format("data.field1: {0}", data.field1));
}
args.data refers to Data instance d2, so args.data.field1 == "handler2" and
your original data field d1 will still have a field value of "Handler1". The
important point to note is when you did:
public class Handler2 : HandlerBase
{
public override void Process(IHandlerArgs args)
{
args.data = new Data();
you replaced what the args instance referenced. What were you expecting to
happen?
Mark.
--
http://www.markdawson.org
"Shailen Sukul" wrote:
Observed a weird behaviour with object references.
See code listing below:
using System;
using System.Collections.Generic;
using System.Text;
namespace PointerExceptionTest
{
/*
Desc: Apparent weird behaviour of encapsulated reference types
getting "lost" upon instance renewal.
The following code example shows a basic implementation of the Chain
of Responsibility design
pattern, where the main class (Orchestrator) creates 2 instances of
the Handler classes, (h1
and h2) and chains them together. It then passes an event argument
variable to h1 by calling
its Process method. The args variable contains a data object that
will be inspected after the
chain is complete. It also contains a data variable that is passed as
a reference to the args constructor.
Handler1 simply changes a value if args.data.field1
Handler2 recreates a new instance of data and assigns it to args.data.
We would expect Orchestration.args.data to be updated to the new
reference of data2 in Handler2 and that DOES happen.
We would also expect Orchestration.data to be updated to the new
reference of data2 in Handler2, but that DOES NOT happen!
When the args.data gets assigned to a new data variable,
Orchestration.data loses reference to the new value from then on.
Being a pointer, one would expect it to be updated, but as the output
clearly shows, it does not.
*/
class Program
{
static void Main(string[] args)
{
Orchestrator o = new Orchestrator();
o.Start();
Console.ReadLine();
}
}
public class Orchestrator
{
IData data = new Data();
IHandlerArgs args = null;
HandlerBase h1 = new Handler1();
HandlerBase h2 = new Handler2();
public void Start()
{
args = new HandlerArgs(data);
h1.successor = h2;
h1.Process(args);
Console.WriteLine(string.Format("args.data.field1:
{0}",args.data.field1));
Console.WriteLine(string.Format("data.field1: {0}", data.field1));
}
}
/* Base class for Handlers */
public abstract class HandlerBase
{
public abstract void Process(IHandlerArgs args);
public HandlerBase successor = null;
}
/* Concrete instance of a handler */
public class Handler1 : HandlerBase
{
public override void Process(IHandlerArgs args)
{
args.data.field1 = "Handerl";
if (successor != null)
{
successor.Process(args);
}
}
}
/* Concrete instance of a handler */
public class Handler2 : HandlerBase
{
public override void Process(IHandlerArgs args)
{
args.data = new Data();
args.data.field1 = "Hander2";
if (successor != null)
{
successor.Process(args);
}
}
}
/* Interface for the argument that is passed to the handler */
public interface IHandlerArgs
{
IData data
{
get;
set;
}
}
/* Concrete instance of HandlerArgs */
public class HandlerArgs : IHandlerArgs
{
public HandlerArgs(IData data)
{
_data = data;
}
IData _data = null;
public IData data
{
get
{
return _data;
}
set
{
_data = value;
}
}
}
/* Interface for the data packet that will be
encapsulated in the HandlerArgs.
*/
public interface IData
{
string field1
{
get;
set;
}
}
/* Concrete instance of a data packet */
public class Data : IData
{
private string _field1 = "null";
public string field1
{
get
{
return _field1;
}
set
{
_field1 = value;
}
}
}
}
--
Good luck!
Shailen Sukul
Architect
(BSc MCTS, MCSD.Net MCSD MCAD)
Ashlen Consulting Service P/L
(http://www.ashlen.net.au)
- Follow-Ups:
- RE: Observation on object references
- From: Ciaran O''Donnell
- RE: Observation on object references
- From: Mark R. Dawson
- RE: Observation on object references
- References:
- Observation on object references
- From: Shailen Sukul
- RE: Observation on object references
- From: Mark R. Dawson
- Observation on object references
- Prev by Date: Re: Observation on object references
- Next by Date: Re: Multiple levels of Null Checking
- Previous by thread: RE: Observation on object references
- Next by thread: RE: Observation on object references
- Index(es):
Relevant Pages
|