2013-07-06 38 views
0

我有这段代码的问题C#结构化列表

我有这样的结构

public struct bounds 
{ 
     public int xmax = 0; 
     public int xmin = 0; 
     public int ymax = 0; 
     public int ymin = 0;   
}; 

和我做一个清单出来的

List<bounds> map = new List<bounds>(); 

我试图存储二维数组中的空间(或对象)的边界(其xmax,xmin,ymin,ymax)我有这个整数y变量,当它到达这个代码时它会变成一些数字,但我不断收到红线UND呃我的列表相关的代码“地图”(i和j是通过二维数组去专柜)

if(!(map.Contains(y))) //if the list doesn't already have this number 
{  
    map.Add(y); 
    map[y].xmax = i; //and set its xmax, xmin, ymax, ymin 
    map[y].xmin = i; 
    map[y].ymax = j; 
    map[y].ymin = j; 
} 

if(map[y].xmax < j)  // if its already in the list look at the current 
    map[y].xmax = j; // boundaries and decide if new ones should be set 

if(map[y].xmin > j) 
    map[y].xmin = j; 

if (map[y].ymax < j) 
    map[y].ymax = i; 

if(map[y].ymin > j) 
    map[y].ymin = i; 
+2

见[为什么可变结构是邪恶的](http://stackoverflow.com/questions/441309/why-are-mutable-structs-vil) –

+0

为什么不使用'System.Drawing.Rectangle'? – ja72

回答

0

要使用List索引,你需要传递一个int。你在这里传递bounds结构

map[y].xmax = i; 

y必须是表示要访问索引的int。我猜y是一个界限结构,因为你使用

map.Add(y); 

和你mapList<bounds>型。

+0

y是一个inte rger –

+2

然后'map.Add(y)'不应该工作。你的'map'列表需要添加一个'bounds'结构,而不是一个整数。 – keyboardP

+0

'y'不能*既是整数也是'map'列表的一个元素,除非你发布的代码根本不是真正的代码。 –

3

原因是这是一个struct是一个值类型。

当您从列表中读出结构体时,您将获得副本

因此,这行代码(以及所有看起来像):

map[y].xmax = i; 

被修改副本从列表中下了车。

您可以通过手动检索副本,修改副本并将其放回列表中来反击。

注意:可变结构会产生各种问题。你遇到的问题只是其中的一个,但你不应该让它们变得可变。

还要注意:您使用的是结构值本身作为索引到列表中,我认为这是一个错误,而你实际使用的指标变量,否则你真的有问题。

尽管这里有一个一般的提示。如果Visual Studio是你的代码下绘制红色squigglies,你可以将鼠标悬停在它得到一个提示,告诉你什么是错的。它可以神秘到你,但错误信息可以用Google搜索容易得多:

example of red squigglies

+1

当然,如果我没有记错的话,它不会编译来说'MethodWhoseReturnTypeIsAMutableStruct()。ChangeableMemberOfStruct = assignThis;'。编辑:不知道如果结构成员是一个字段或属性在这里(?)是否重要。 –

0

如果数据类型的目的是封装固定的一组相关的,但独立的值(如的坐标点),暴露的字段结构比任何其他数据类型更好地满足该描述。除了覆盖ToString()Equals()GetHashCode()之外,此类结构不应具有许多实例方法;结构使用静态工具方法通常比实例方法更好。例如,这会是有问题:

public void UpdateRange(Point pt) 
{ 
    if (pt.X > xmax) xmax = pt.X; 
    if (pt.Y > ymax) ymax = pt.Y; 
    if (pt.X < xmin) xmin = pt.X; 
    if (pt.Y < ymin) ymin = pt.Y; 
} 

但这并不:

public void UpdateRange(ref bounds it, Point pt) 
{ 
    if (pt.X > it.xmax) it.xmax = pt.X; 
    if (pt.Y > it.ymax) it.ymax = pt.Y; 
    if (pt.X < it.xmin) it.xmin = pt.X; 
    if (pt.Y < it.ymin) it.ymin = pt.Y; 
} 

注意,当类公开的结构类型的属性,这是不可能直接修改这些性质。一个人不能使用这样的:

bounds.UpdateRange(ref myList[4], newPoint); 

也没有,如果UpdateRange是一个实例方法,可能一个用途:

myList[4].UpdateRange(newPoint); 

在后一种情况下,代码编译,但不会工作。相反,人们必须使用类似:

var temp = myList[4]; 
bounds.UpdateRange(ref temp, newPoint); 
mylist[4] = temp; 

注意,实例方法,并用ref参数的静态方法是在情况下,都将编译语义相同。它们之间的区别在于,只有在ref参数是可修改变量的情况下,具有ref参数的静态方法才会编译,但在属性上调用实例方法会导致编译器将该属性复制到临时变量,请调用实例方法,并丢弃结果。

我建议你的类型几乎是一个应该是结构的东西的完美例子。如果它是一个可变类类型,那么通过引用实例的代码是否确实传递实例在调用时碰巧保留的瞬时值,或者是否将引用传递给“活”实体。使用不可变的类类型或所谓的不可变结构类型[请注意,实际上并不存在任何不可变的值类型]会使像UpdateRange这样的方法编写和运行变得更慢,同时不会提供特别的好处。

关于结构类型需要注意的一点是,每个字段(例如xmin)除了“存储在”xmin“中的最后一个值之外没有其他含义,如果没有存储在那里,则为零。代码编写256 xmin和-234至xmax,然后xmin将举行256和xmax -234. Any code which takes a bounds`并没有与它有什么要对这种值准备只是因为这将是,如果它把这些字段作为四个单独的参数。