这可能有点像一个愚蠢的问题,但我似乎无法找到有关这种行为的任何信息。
以下是代码:
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变量设置为指针或其他东西。如何避免这种情况?我认为这就是“新”关键字的成就。
提前感谢您的帮助。
答案 0 :(得分:5)
因为Cars
是一个对象,而C#中的对象是Reference Types
。
当你拨打这行代码时:
oneCar = manyCars[2];
您将oneCar
指向manyCars[2]
的内存位置。它们引用相同的对象。更新oneCar
也会更新manyCars[2]
。
This link对参考和值类型有很好的写作。
答案 1 :(得分:3)
manyCars[2]
是福特。所以在分配后oneCar
是同一个福特。但请记住,类类型是引用类型。这意味着oneCar
和manyCars[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();
现在oneCar
和manyCars[2]
是两个不同的对象,更改oneCar's
模型不会影响manyCars[2]
的模型。
答案 2 :(得分:2)
在c#中有值和引用类型 - 类是引用类型。上面的代码在ManyCars列表中添加了三个新的汽车对象 - 然后将OneCar变量设置为第三个列表元素的引用 - 在您的情况下为F150。然后用Pinto覆盖模型属性,然后遍历列表。
您基本上将OneCar设置为指向原始Car对象的指针。如果要创建对象的副本,然后可以更改而不影响List中的原始对象,则需要克隆Car对象,而不仅仅是将其分配给OneCar变量。
干杯 西蒙