2012-10-02 31 views
3

这可能有点不好意思,但我似乎无法找到有关此行为的任何信息。C#单行列表行为

下面是代码:

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(); 
    } 
} 

输出是这样的:

1993Nissan240SX

2001IsuzuRodeo

2010FordPinto

2010FordPinto

为什么第三行读取Pinto而不是F150?它似乎将oneCar变量设置为指针或其他东西。这怎么可以避免?我认为这就是“新”关键字所完成的。

在此先感谢您的帮助。

+4

请仔细阅读http://pobox.com/~skeet/csharp/references.html –

+1

您将需要克隆manyCars [2],然后进行更改克隆的对象。 – d89761

回答

5

因为Cars是一个对象,在C#中的对象是Reference Types

当你调用这行代码:

oneCar = manyCars[2]; 

您都指向oneCarmanyCars[2]的存储位置。他们正在引用同一个对象。更新oneCar也更新manyCars[2]

This link在Reference和Value类型上有很好的写法。

+0

谢谢了,精确地回答了我的问题。不知道引用/值类型的处理方式不同。 –

3

manyCars[2]是福特。所以在分配oneCar之后是同一辆福特。但请记住,类的类型是引用类型。这意味着oneCarmanyCars[2]指向相同的汽车对象!因此设置oneCar.model = "Pinto"的效果与设置manyCars[2].model = "Pinto"的效果相同。

oneCar = manyCars[2];不会创建对象内容的副本。你可以一个Clone方法添加到汽车类

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

那么这真的创建了一个副本

oneCar = manyCars[2].Clone(); 

现在oneCarmanyCars[2]是两个不同的对象,改变oneCar's模式不会影响manyCars[2]模型。

2

在c#中有值和引用类型 - 一个类是引用类型。上面的代码将三个新车对象添加到ManyCars列表中 - 然后将OneCar变量设置为第三个列表元素的引用 - 在您的情况下为F150。然后用Pinto覆盖模型属性,然后遍历列表。

你已经基本上将OneCar设置为指向原始Car对象的指针。如果您想制作一个对象的副本,然后在不影响列表中的原始对象的情况下进行更改,则需要克隆Car对象,而不是将其分配给OneCar变量。

干杯 西蒙