Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# odd list behavior

Tags:

c#

list

pointers

This may be somewhat of a noobish question but I cannot seem to find any information on this behavior at all.

Here is the code:

class Cars
{
    public int year = 0;
    public string make = " ";
    public string model = " ";

    public Cars()
    {
    }

    public Cars(int tYear, string tMake, string tModel)
    {
        year = tYear;
        make = tMake;
        model = tModel;
    }

    public string ConvertToString()
    {
        return year.ToString() + make + model;
    }
}

class Program
{
    Cars oneCar = new Cars();
    List<Cars> manyCars = new List<Cars>();

    public void Init()
    {
        manyCars.Add(new Cars(1993, "Nissan", "240SX"));
        manyCars.Add(new Cars(2001, "Isuzu", "Rodeo"));
        manyCars.Add(new Cars(2010, "Ford", "F150"));

        oneCar = manyCars[2];
        oneCar.model = "Pinto";

        for (int i = 0; i < manyCars.Count(); i++)
            Console.WriteLine(manyCars[i].ConvertToString());

        Console.WriteLine(oneCar.ConvertToString());
    }

    static void Main(string[] args)
    {
        Program prg1 = new Program();
        prg1.Init();
    }
}

The output is this:

1993Nissan240SX

2001IsuzuRodeo

2010FordPinto

2010FordPinto

Why is the third line reading Pinto instead of F150? It seems to be setting the oneCar variable to be a pointer or something. How can this be avoided? I thought that's what the "new" keyword accomplished.

Thanks in advance for any help.

like image 445
Mike Jones Avatar asked Sep 25 '26 01:09

Mike Jones


2 Answers

Because Cars is an object, and objects are Reference Types in C#.

When you call this line of code:

oneCar = manyCars[2];

You are pointing oneCar to the memory location of manyCars[2]. They are referencing the same object. Updating oneCar also updates manyCars[2].

This link has a good writeup on Reference and Value types.

like image 95
Dave Zych Avatar answered Sep 26 '26 15:09

Dave Zych


manyCars[2] is the Ford. So after the assignement oneCar is the same Ford. But remember that class types are reference types. This means that oneCar and manyCars[2] point to the same car object! Therefore setting oneCar.model = "Pinto" has the same effect than setting manyCars[2].model = "Pinto".

oneCar = manyCars[2]; does not create a copy of the objects content. You could add a Clone method to the cars class

public Cars Clone()
{
    return (Cars)MemberwiseClone(); // This method is inherited from object.
}

Then this really creates a copy

oneCar = manyCars[2].Clone();

Now oneCar and manyCars[2] are two distinct objects and changing oneCar's model won't affect the model of manyCars[2].

like image 45
Olivier Jacot-Descombes Avatar answered Sep 26 '26 15:09

Olivier Jacot-Descombes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!