Alex Rivera | Logout

Value assignment for reference type in C#

Asked 2009-06-30T19:59:21.067
10

What is the proper way to implement assignment by value for a reference type? I want to perform an assignment, but not change the reference.

Here is what I'm talking about:

void Main()
{
    A a1 = new A(1);
    A a2 = new A(2);
    a1 = a2; //WRONG: Changes reference
    a1.ValueAssign(a2); //This works, but is it the best way?
}

class A
{
    int i;

    public A(int i)
    {
        this.i = i;
    }

    public void ValueAssign(A a)
    {
        this.i = a.i;
    }
}

Is there some sort of convention I should be using for this? I feel like I'm not the first person that has encountered this. Thanks.

EDIT:

Wow. I think I need to tailor my question more toward the actual problem I'm facing. I'm getting a lot of answers that do not meet the requirement of not changing the reference. Cloning is not the issue here. The problem lies in ASSIGNING the clone.

I have many classes that depend on A - they all share a reference to the same object of class A. So, whenever one classes changes A, it's reflected in the others, right? That's all fine and well until one of the classes tries to do this:

myA = new A();

In reality I'm not doing new A() but I'm actually retrieving a serialized version of A off the hard drive. But anyways, doing this causes myA to receive a NEW REFERENCE. It no longer shares the same A as the rest of the classes that depend on A. This is the problem that I am trying to address. I want all classes that have the instance of A to be affected by the line of code above.

I hope this clarifies my question. Thank you.

Edit
Report

3 Answers

2

I believe you should be using a struct instead of a class than, as structs work by value and not by reference.

answered 2009-06-30T20:01:07.333
1

Others have suggested cloning in their answer, but that's only part of the deal. You also want to use the results of a (possibly deep) clone to replace the contents of an existing object. That's a very C++-like requirement.

It just doesn't come up very often in C#, so there's no standard method name or operator meaning "replace the contents of this object with a copy of the contents of that object".

The reason it occurs so often in C++ is because of the need to track ownership so that cleanup can be performed. If you have a member:

std::vector<int> ints;

You have the advantage that it will be properly destroyed when the enclosing object is destroyed. But if you want to replace it with a new vector, you need swap to make that efficient. Alternatively you could have:

std::vector<int> *ints;

Now you can swap in a new one easily, but you have to remember to delete the old one first, and in the enclosing class's destructor.

In C# you don't need to worry about that. There's one right way:

List<int> ints = new List<int>();

You don't have to clean it up, and you can swap in a new one by reference. Best of both.

Edit:

If you have multiple "client" objects that need to hold a reference to an object and you want to be able to replace that object, you would make them hold a reference to an intermediate object that would act as a "wrapper".

class Replaceable<T>
{
    public T Instance { get; set; }
}

The other classes would hold a reference to the Replaceable<T>. So would the code that needs to swap in a replacement. e.g.

Replaceable<FileStream> _fileStream;

It might also be useful to declare an event, so clients could subscribe to find out when the stored instance was replaced.

0

If I got it right, you are talking about proper Singleton deserialization.

  1. If you are using .Net native serialization then you might take a look at the MSDN ISerializable example. The example shows exactly that - how to override ISerializable.GetObjectData to return the same instance on each call.

  2. If you are using Xml serialization (XmlSerializer), then you manually implement IXmlSerializable in your object's parent class, and then take care to get a single instance each time.

  3. A simplest way would be to ensure this in your parent property's setter, by accessing some kind of a static cache. (I find this pretty dirty, but that's an easy way to do it).

For example:

 public class ParentClass
 {
      private ReferencedClass _reference;
      public ReferencedClass Reference
      {
          get
          { 
              return _reference;
          }
          set
          {
              // don't assign the value, but consult the
              // static dictionary to see if we already have
              // the singleton
              _reference = StaticCache.GetSingleton(value);
          }
      }
 }

And then you would have a static class with some kind of a dictionary where you could quickly retrieve the singleton instance (or create it if it doesn't exist).

Although this may work for you, I also agree with the others that this is rarely the best (or only) way to do it. There is surely a way to refactor your code so that this becomes unnecessary, but you should provide some additional info about what is the intended usage, where is this data accessed from, or simply why do classes really need to reference a single object.

[Edit]

answered 2009-06-30T21:17:26.040

Your Answer