0

我对这段代码有问题

我有这个结构

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)中我在与我的列表“地图”关联的代码下不断出现红线(i 和 j 是用于遍历 2D 数组的计数器)

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;
4

3 回答 3

3

原因是结构是值类型。

当您从列表中读出结构时,您将获得一份.

因此,这行代码(以及所有类似的代码):

map[y].xmax = i;

正在修改您从列表中取出的副本。

您可以通过手动检索副本、修改副本并将其放回列表来解决此问题。

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

另请注意:您将结构值本身用作列表的索引器,我认为这是一个错误,并且您实际上正在使用索引变量,否则您确实遇到了问题。

不过,这里有一个一般提示。如果 Visual Studio 在您的代码下绘制红色波浪线,您可以将鼠标悬停在它上面以获得一个工具提示,告诉您哪里出了问题。它可能对您来说很神秘,但可以更轻松地搜索错误消息:

红色波浪线的例子

于 2013-07-06T18:46:38.770 回答
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 abounds` 并且对它做任何事情都应该为这些值做好准备,就像将这些字段作为四个单独的参数一样。

于 2013-07-08T15:38:09.770 回答
0

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

map[y].xmax = i;

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

map.Add(y);

而你map的类型是List<bounds>

于 2013-07-06T18:46:22.417 回答