简体   繁体   中英

.NET/C#: Is it possible to replace one object in memory with another?

Take this code for example:

class Jooky
{
    static long Last;
    public Jooky() { Id += Last++; }
    public long Id { get; set; }
    public string Name { get; set; }
}

class Flooky
{
    public Flooky() { Jooky1 = new Jooky(); Jooky2 = new Jooky(); }
    public Jooky Jooky1 { get; set; }
    public Jooky Jooky2 { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        List<Flooky> Flookies = new List<Flooky>();

        //I build a collection of flookies to emulate the service call of
        //FlookyProxy.GetAllFlookies().
        for (int i = 0; i < 5; i++) Flookies.Add(new Flooky());

        //This makes a collection of all the jookies in all the flookies.
        var Jookies = Flookies.Select(f => f.Jooky1).Union(Flookies.Select(f => f.Jooky2));

        //I get the jooky.
        Jooky Jooky = Jookies.Single(j => j.Id == 2);

        //Fig 1: I just got a jooky out of the collection. One of the flookies
        //has a reference to this jooky. I want to set the jooky to a new
        //reference, but still want the same flooky to reference it.
        Jooky = new Jooky { Name = "Bob" };

        //I get the jooky again
        Jooky = Jookies.Single(j => j.Id == 2);

        //However, this writes an empty string because only the Jooky variable
        //I previously declared was affected.
        Console.WriteLine(Jookies.Single(j => j.Id == 2).Name);

        //Basically, I want the code in Fig 1 above to be the same as:
        //Flooy.Jooky = new Jooky { Name = "Bob" };

        Console.Read();
    }
}

Basically, variable A is referencing Aa in memory and variable B is referencing object Bb in memory. I want to make A reference the same object in memory as B without going like A = B; . Instead, I want to replace the physical object in memory with another, ultimately going like Aa = Bb; .

Is this at all possible?

Update: Primary rule: I cannot reference the flooky directly, so I can't be all like Flooky.Jooky1 = new Jooky() or Flookies[3].Jooky1 = new Jooky() .

Change:

//Jooky = new Jooky { Name = "Bob" };
Jooky.Name = "Bob" ;

The resullt of the .Single() is a reference to an instance (object). You were just overwriting the reference with one to a new object. The old object was not changed or overwritten.

To understand what's going on, and to adjust what you are aiming for, look up "Value Type and Reference Type". Lots of reading to do.


After reading the comment:

If your Details (Jookies) are going to change independently of their Owners (the Flookies) then you just need another layer of indirection.

A simple suggestion:

  • do not store references to the details (since they will change)
  • store a DetailId instead (JookyId1, JookyId2)
  • keep the Details in a Dictionary ( Dictionary<int,Jooky> )
  • create a (readonly) property in Owner to get Detail1 by looking it up in the dictionary.

Maybe this is possible with unsafe code as suggested by havardhu, but it's definitely not possible with safe code. It's important to understand why doing what you're trying to do is unsafe. Not only does it break encapsulation, it breaks type safety. Consider this example.

class Me : IHaveCar
{
    BuickCentury myCentury = new BuickCentury(2004);

    public Car Car { get { return myCentury; } }

    public void Drive()
    {
        myCentury.CruiseWithAuthority();
    }
}

class EvilOilChangeService
{
    public void ChangeOil(IHaveCar customer)
    {
        Car car = customer.Car;
        // here's the fictional "replace object in memory" operator
        car <<== new VolkswagenBeetle(2003);
    }
}

The EvilOilChangeService can create a situation where myCentury is referencing a VolkswagenBeetle ! I'm going to be in trouble when I try to go for a Drive because a VolkswagenBeetle just can't CruiseWithAuthority like a BuickCentury can (especially when the driver is 6'2")

Even in C/C++ which allows willy-nilly memory access, I would still be quite surprised by code that does what you want to do. This is why most of the other answers are suggesting a different approach or design.

You can write unsafe code in C# which enables you to operate on direct memory.

Have a look here for details:

Pointers and arrays in C#

You'll notice that you can use the familiar pointers (*) and addresses (&) from C and C++.

Here's an example of an unsafe swap, which I think is what you're after: Unsafe swap in C#

Jooky = new Jooky { Name = "Bob" }; 
Flookies[0].Jooky1=Jooky;

If you want to replace and object with another without just assigning references you just to copy all the data fields to the other object. Not sure if i have understood your question correctly.

When you're working with references, every assignment to a reference changes the object that reference points to.

So, when you say:

Jooky Jooky = Jookies.Single(j => j.Id == 2);

you're creating a reference to the Jookie with Id == 2 . And then, when you say Jooky = new Jooky { Name = "Bob" }; , you're telling that reference you created to point to the Jooky you have just created instead.

So, if you want to set a new value to the Jookie1 property (wich is a placeholder for a reference to a Jookie object) of the Flookies[0] object, you got to say:

Flookies[0].Jooky1 = new Jooky { Name = "Bob" }; (as stated by @Ashley John's answer).

That way, you're telling the Flookies[0].Jooky1 reference to point to the new Jooky { Name = "Bob" }; object.

For further explanation, see http://msdn.microsoft.com/en-us/library/ms173104.aspx .

If you have access to the Jookie class, you could add a property that holds the parent Flookie of the Jookie :

class Jooky 
{
    static long Last;
    public Jooky(Flooky parent) 
    {
        Id += Last++; 
        Parent = parent;
    }
    public long Id { get; set; }
    public string Name { get; set; }
    public Flooky Parent { get; private set; }
}

and then access the parent Flookie and change it's Jookie1 property:

Flookie flookie = Jookies.Single(j => j.Id == 2).Parent;
flookie.Jookie1 = new Jookie { Name = "Bob" }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM