令人费解的收藏品 [英] Puzzling Collections

查看:68
本文介绍了令人费解的收藏品的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我附上以下代码和输出。我将一个对象添加到

集合中。我修改了对象的属性。

集合中的项目也会被修改。你能帮我确定一下我在哪里吗?b $ b出错了。谢谢。

公共类形状

{

protected size _size;

protected Point _location;


公共尺寸

{

get {return _size;}

set {_size = value;} < br $>
}


公共点位置

{

get {return _location;}

set {_location = value;}

}


public Shape()

{}

}

公共类Rect:Shape

{

public Rect(Point loc,Size size):base()

{

_size = size;

_location = loc;

}

}


//第二个例子

公共类ShapeCollection:CollectionBase

{

public ShapeCollection() :base()

{}


public void Add(Shape s)

{this.List.Add(s) ; }


public Shape this [int index]

{

get

{return(Shape) )列表[指数]; }


设定

{List [index] = value; }

}

}


公共类RectanglesCollection:CollectionBase

{

public RectanglesCollection():base()

{}

public void Add(Rectangle r)

{this.List.Add (R); }


public Rectangle this [int index]

{

get

{return(Rectangle) )列表[指数]; }

set

{List [index] = value; }

}

}


public void test()

{

ShapeCollection shapes = new ShapeCollection();

Rect rect = new Rect(new Point(0,0),new Size(50,50));

shapes.Add(rect);

Debug.WriteLine(" 1st item:" + shapes [0] .Location.ToString());


rect.Location = new Point(2,2); //更改.Location属性

Debug.WriteLine("'1st item again:" +

shapes [0] .Location.ToString()+"为什么? !);


shapes.Add(rect);


foreach(Shape sh in shapes)Debug.WriteLine

(sh.Location.ToString());


Debug.WriteLine(" ==============");


RectanglesCollection rectanglesCollection = new

RectanglesCollection();

Rectangle r = new Rectangle(new Point(0,0),新尺寸(100,50));

rectanglesCollection.Add(r);

r.Location = new Point(5,5); //更改.Location属性

Debug.WriteLine(&r;修改后的列表项:" +

rectanglesCollection [0] .ToString());

rectanglesCollection.Add(r);

foreach(RectanglesCollection中的矩形rx)

Debug.WriteLine(rx.ToString());

}

输出:

-------


第1项:{X = 0 ,Y = 0}

第一项:{X = 2,Y = 2}为什么?!

{X = 2,Y = 2}

{X = 2,Y = 2}

==============

r修改后的列表项:{ X = 0,Y = 0,宽度= 100,高度= 50}

{X = 0,Y = 0,宽度= 100,高度= 50}

{ X = 5,Y = 5,宽度= 100,高度= 50}

I attach the following code and output. I Add an object to a
Collection. I modified a property of the object. The item in the
Collection gets modifed also. Can you help me determine where I have
gone wrong. Thanks.
public class Shape
{
protected Size _size;
protected Point _location;

public Size Size
{
get{return _size;}
set{_size=value;}
}

public Point Location
{
get{return _location;}
set{_location=value;}
}

public Shape()
{ }
}
public class Rect : Shape
{
public Rect(Point loc, Size size) : base()
{
_size = size;
_location = loc;
}
}

// For second example
public class ShapeCollection : CollectionBase
{
public ShapeCollection() : base()
{ }

public void Add(Shape s)
{ this.List.Add(s); }

public Shape this[int index]
{
get
{ return (Shape)List[index]; }

set
{ List[index]=value; }
}
}

public class RectanglesCollection : CollectionBase
{
public RectanglesCollection() : base()
{ }
public void Add(Rectangle r)
{ this.List.Add(r); }

public Rectangle this[int index]
{
get
{ return (Rectangle)List[index]; }
set
{ List[index]=value; }
}
}

public void test()
{
ShapeCollection shapes = new ShapeCollection();
Rect rect = new Rect (new Point(0,0), new Size(50,50));
shapes.Add(rect);
Debug.WriteLine("1st item: " + shapes[0].Location.ToString());

rect.Location=new Point(2,2); //Change .Location property
Debug.WriteLine("1st item again: " +
shapes[0].Location.ToString() + " Why?!");

shapes.Add(rect);

foreach (Shape sh in shapes) Debug.WriteLine
(sh.Location.ToString());

Debug.WriteLine("==============");

RectanglesCollection rectanglesCollection = new
RectanglesCollection();
Rectangle r = new Rectangle(new Point(0,0), new Size(100,50));
rectanglesCollection.Add(r);
r.Location = new Point(5,5); // change the .Location property
Debug.WriteLine("List item after r modified: " +
rectanglesCollection[0].ToString());
rectanglesCollection.Add(r);
foreach (Rectangle rx in rectanglesCollection)
Debug.WriteLine(rx.ToString());
}
Output:
-------

1st item: {X=0,Y=0}
1st item again: {X=2,Y=2} Why?!
{X=2,Y=2}
{X=2,Y=2}
==============
List item after r modified: {X=0,Y=0,Width=100,Height=50}
{X=0,Y=0,Width=100,Height=50}
{X=5,Y=5,Width=100,Height=50}

推荐答案

嗨苏&比尔,

你没有做错任何错误,这是你应该得到的预期行为。基本上在.Net中有两种主要类型的变量:值和

参考。赋值时复制值变量即


int i = 3;

int j = i;

j + = 1;


- >现在我仍然是3,j是4


这是因为当你传递它们时会复制值类型 - 我认为

这是你所期待的在下面的代码中发生。


但是,其他类型的引用类型不会被复制。这适用于

所有对象,它们都是引用类型(字符串表现得有点不同,但是我们不会在这里进行讨论)。在这种情况下,你的变量

不包含实际数据,但实际上只是对象的引用

ie


MyClass c1 = new MyClass();

c1.Name =" c1" ;;

MyClass c2 = c1;

c2.Name =" c2


- >现在c1.Name和c2.Name都将返回c2


c1,c2引用MyClass对象的同一个实例


c1 ------

\

---------------- MyClass Instance

c2 ------ /

当你将一个项目添加到一个集合中时,你实际上只是将一个引用

传递给该对象,而不是实际的对象本身,所以如果你以任何方式修改对象'

状态,那么当你访问集合中的引用时,

指向修改后的对象,它显然会显示修改后的状态。

如果你不希望修改集合中的项目,你应该在将它放入集合之前创建一个对象的克隆 - 这个是
a副本的对象,查看ICloneable界面。

希望有所帮助

Mark R Dawson

苏&比尔"写道:
Hi Sue & Bill,
you have done nothing wrong this is the expected behaviour that you should
get. Basically in .Net there are two main types of variables: Value and
References. Value variables get copied when assigned i.e.

int i = 3;
int j = i;
j += 1;

--> now i is still 3 and j is 4

This is because value types get copied when you pass them round - I think
this is what you were expecting to happen in your code below.

However, the other type, reference types do not get copied. This applies to
all objects, which are reference types (strings behave a little bit
differently, but we will not go into that here). In this case your variable
does not contain the actual data but really just a reference to the object
i.e.

MyClass c1 = new MyClass();
c1.Name = "c1";
MyClass c2 = c1;
c2.Name = "c2"

--> Now both c1.Name and c2.Name will return "c2"

c1,c2 are referencing the same instance of the MyClass object

c1 ------
\
---------------- MyClass Instance
c2 ------/
When you add an item to a collection you are really just passing a reference
to the object, not the actual object itself, so if you modify the object''s
state in any way then when you access the reference in the collection which
is pointing to the modified object it will obviously show the modified state.
If you do not want the item in the collection to get modified you should
create a clone of the object before you put it intto the collection - this is
a duplicate copy of the object, look into the ICloneable interface.
Hope that helps
Mark R Dawson

"Sue & Bill" wrote:
我附上以下代码和输出。我将一个对象添加到
集合中。我修改了对象的属性。
集合中的项目也会被修改。你能帮我确定一下我出错了吗?谢谢。

公共类形状
{
受保护尺寸_size;
受保护点_location;

公共尺寸
{
获取{return _size;}
设置{_size = value;}
}
公共点位置
{get / return _location ;}
设置{_location = value;}
}
公共形状()
{}
}

public class Rect:Shape
{public Rect(Point loc,Size size):base()
{
_size = size;
_location = loc;
}
}
//第二个例子
公共类ShapeCollection:CollectionBase
公共ShapeCollection():base()
{}

public void Add(Shape s)
{this.List.Add(s);公共形状这个[int index]
{
get
{return(Shape)List [index]; }

设置
{List [index] = value;公共类RectanglesCollection:CollectionBase
公共RectanglesCollection():base()
{}
public void Add(Rectangle r)
{this.List.Add(r);这个[int index]
{
获取
{return(Rectangle)List [index]; }
设置
{List [index] = value; }
}

公共空洞测试()
{
ShapeCollection shapes = new ShapeCollection();
Rect rect = new Rect (new Point(0,0),new Size(50,50));
shapes.Add(rect);
Debug.WriteLine(" 1st item:" + shapes [0]。 Location.ToString());

rect.Location = new Point(2,2); //更改.Location属性
Debug.WriteLine("'1st item again:" +
shapes [0] .Location.ToString()+" Why?!");

shapes.Add(rect);

foreach(Shape sh in shapes)Debug.WriteLine
(sh.Location.ToString());

Debug.WriteLine(" ==============");

RectanglesCollection rectanglesCollection = new
RectanglesCollection();
Rectangle r = new Rectangle(new Point(0,0),new Size(100,50));
rectanglesCollection.Add(r);
r.Location = new Point(5,5); //更改.Location属性
Debug.WriteLine(&r;修改后的列表项:" +
rectanglesCollection [0] .ToString());
rectanglesCollection.Add(r) ; foreach(Rectangles集合中的矩形rx)
Debug.WriteLine(rx.ToString());
}

输出:
---- ---

第1项:{X = 0,Y = 0}
第1项:{X = 2,Y = 2}为什么?!
{X = 2,Y = 2}
{X = 2,Y = 2}
==============
r修改后的列表项:{X = 0,Y = 0,宽度= 100,高度= 50}
{X = 0,Y = 0,宽度= 100,高度= 50}
{X = 5,Y = 5,宽度= 100,身高= 50}
I attach the following code and output. I Add an object to a
Collection. I modified a property of the object. The item in the
Collection gets modifed also. Can you help me determine where I have
gone wrong. Thanks.
public class Shape
{
protected Size _size;
protected Point _location;

public Size Size
{
get{return _size;}
set{_size=value;}
}

public Point Location
{
get{return _location;}
set{_location=value;}
}

public Shape()
{ }
}
public class Rect : Shape
{
public Rect(Point loc, Size size) : base()
{
_size = size;
_location = loc;
}
}

// For second example
public class ShapeCollection : CollectionBase
{
public ShapeCollection() : base()
{ }

public void Add(Shape s)
{ this.List.Add(s); }

public Shape this[int index]
{
get
{ return (Shape)List[index]; }

set
{ List[index]=value; }
}
}

public class RectanglesCollection : CollectionBase
{
public RectanglesCollection() : base()
{ }
public void Add(Rectangle r)
{ this.List.Add(r); }

public Rectangle this[int index]
{
get
{ return (Rectangle)List[index]; }
set
{ List[index]=value; }
}
}

public void test()
{
ShapeCollection shapes = new ShapeCollection();
Rect rect = new Rect (new Point(0,0), new Size(50,50));
shapes.Add(rect);
Debug.WriteLine("1st item: " + shapes[0].Location.ToString());

rect.Location=new Point(2,2); //Change .Location property
Debug.WriteLine("1st item again: " +
shapes[0].Location.ToString() + " Why?!");

shapes.Add(rect);

foreach (Shape sh in shapes) Debug.WriteLine
(sh.Location.ToString());

Debug.WriteLine("==============");

RectanglesCollection rectanglesCollection = new
RectanglesCollection();
Rectangle r = new Rectangle(new Point(0,0), new Size(100,50));
rectanglesCollection.Add(r);
r.Location = new Point(5,5); // change the .Location property
Debug.WriteLine("List item after r modified: " +
rectanglesCollection[0].ToString());
rectanglesCollection.Add(r);
foreach (Rectangle rx in rectanglesCollection)
Debug.WriteLine(rx.ToString());
}
Output:
-------

1st item: {X=0,Y=0}
1st item again: {X=2,Y=2} Why?!
{X=2,Y=2}
{X=2,Y=2}
==============
List item after r modified: {X=0,Y=0,Width=100,Height=50}
{X=0,Y=0,Width=100,Height=50}
{X=5,Y=5,Width=100,Height=50}



马克,谢谢你的解释。


是的,我知道价值和参考类型。这就是为什么我在第二个例子中包含了一个

的原因。第二个例子也是将对象添加到

集合,但结果不同。你介意再拿一个

的样子。


(勘误:对于第二个例子,评论应该是一个块。)


无论如何,关于IList.Add的总文档说当用

a类实现时,会向IList添加一个项目。它没有给出最轻微的提示是否通过引用或复制添加项目。


提前致谢。

Mark, thanks for the explanation.

Yes, I kow about value and reference types. That''s why I included a
second example. The second example is also Adding objects to a
Collection but the result is different. Do you mind taking another
look.

(Errata: the "// For second example" remark should be one block down.)

Anyway, the total documentation on IList.Add says "When implemented by
a class, adds an item to the IList." It does not give the slightest
hint whether an item is Added by reference or by copying.

Thanks in advance.


Hi Sue&比尔,

啊 - 对不起刚吃完我的weetabix就醒了回来,总是不好做的事情,现在我的血管周围有一些糖,我看到更多

很清楚,我没有注意到你在你的例子中使用了Rect和Rectangle。


在你的第一个例子中,你将Rect类的实例添加到集合中:


ShapeCollection shapes = new ShapeCollection();

Rect rect = new Rect(new Point(0,0),new Size(50,50) );

shapes.Add(rect);

Console.WriteLine(" 1st item:" + shapes [0] .Location.ToString());


rect.Location = new Point(2,2); //更改.Location属性

Console.WriteLine("第一项:&+; shapes [0] .Location.ToString()+"

为什么? !");

shapes.Add(rect);


foreach(形状中的形状)

Console.WriteLine (sh.Location.ToString());

您的rect类作为refence传递到集合中,因此您将Location属性修改为

因此集合中的引用和

你的rect变量仍然指向同一个对象,这就是为什么你看到的结果:

{X = 2,Y = 2}

{X = 2,Y = 2}

输出。


在你的第二个例如,您将矩形结构添加到

集合中。这个类型是一个结构而不是一个类,结构通过值

传递到集合中,即当你将它添加到集合中时,会创建一个对象的副本。所以在你将矩形的COPY添加到

集合后说:


r.Location = new Point(5,5);


你正在改变r变量实例的位置而不是现在在集合中的矩形的复制品




判断类是值类型还是引用类型的简单方法是在.Net文档中查看

并查看对象是否继承自

System.ValueType如果是,那么它将具有ValueType语义,例如

Rectangle类。


您可能也想查看Boxing和Unboxing帮助你更多这个话题




希望有所帮助

Mark R Dawson。

苏&比尔"写道:
Hi Sue & Bill,
ah - sorry just woken up and answered before eating my weetabix, always a
bad thing to do, now I have some sugar pumping around my veins I see more
clearly, I did not notice you were using Rect and Rectangle in your examples.

In your first example you add instances of your Rect class to the collection:

ShapeCollection shapes = new ShapeCollection();
Rect rect = new Rect (new Point(0,0), new Size(50,50));
shapes.Add(rect);
Console.WriteLine("1st item: " + shapes[0].Location.ToString());

rect.Location=new Point(2,2); //Change .Location property
Console.WriteLine("1st item again: " +shapes[0].Location.ToString() + "
Why?!");
shapes.Add(rect);

foreach (Shape sh in shapes)
Console.WriteLine(sh.Location.ToString());
Your rect class is passed as a refence into the collection, so you modify
the Location property to be 2,2 therefore the reference in the collection and
your rect variable are still pointing to the same object that is why you are
seeing:
{X=2,Y=2}
{X=2,Y=2}
in your output.

In your second example, you are adding Rectangle structures into the
collection. This type is a struct not a class, structs are passed by value
into the collection, i.e. a copy is created of the object when you add it to
the collection. So after you have added a COPY of the rectangle into the
collection and say:

r.Location = new Point(5,5);

you are changing the location of the r variable instance but not the COPY of
the rectangle which is now in the collection.

An easy way to tell if a class is a value type or reference type is to look
at the .Net documentation and see if the object inherits from
System.ValueType if so then it will have ValueType semantics, such as the
Rectangle class does.

You might want to look into Boxing and Unboxing as well to help you more in
this topic.

Hope that helps
Mark R Dawson.

"Sue & Bill" wrote:
马克,谢谢你的解释。

是的,我知道价值和参考类型。这就是我加入第二个例子的原因。第二个例子也是将对象添加到
集合,但结果是不同的。你介意再看看吗

(勘误:对于第二个例子的评论应该是一个块。)

无论如何,关于IList.Add的总文档说当通过类实现时,向IList添加一个项目。它没有给出最轻微的暗示是否通过引用或复制添加项目。

提前致谢。
Mark, thanks for the explanation.

Yes, I kow about value and reference types. That''s why I included a
second example. The second example is also Adding objects to a
Collection but the result is different. Do you mind taking another
look.

(Errata: the "// For second example" remark should be one block down.)

Anyway, the total documentation on IList.Add says "When implemented by
a class, adds an item to the IList." It does not give the slightest
hint whether an item is Added by reference or by copying.

Thanks in advance.



这篇关于令人费解的收藏品的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆