簡體   English   中英

C#結構化清單

[英]C# Structured List

我在這段代碼上遇到問題

我有這個結構

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

我正在嘗試將空間(或對象)的邊界存儲在2D數組(其xmax,xmin,ymin和ymax)中,我有這個整數y變量,到達此代碼時它將是一些數字,但是在與列表“地圖”關聯的代碼下,我不斷出現紅線(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;

這是因為結構是值類型。

當您從列表中讀取結構時, 會得到一個副本

這樣,這行代碼(以及所有類似的代碼):

map[y].xmax = i;

正在修改您從列表中得到的副本

您可以通過手動獲取副本,對其進行修改並將其放回列表中來應對。

注意:可變結構會產生各種問題 您遇到的問題只是其中之一,但您不應該使它們變得易變。

另請注意:您將struct值本身用作列表的索引器,我認為這是一個錯誤,並且您實際上在使用索引變量,否則您確實遇到了問題。

這是一個一般性提示。 如果Visual Studio在您的代碼下繪制紅色曲線,則可以將鼠標懸停在其上方以獲取提示信息,告訴您出了什么問題。 它可能對您來說很晦澀,但可以通過Google輕松搜索錯誤消息:

紅色波浪狀的例子

要使用List索引器,您需要傳遞一個int值。 您在此處傳遞了一個bounds結構

map[y].xmax = i;

y必須是一個表示要訪問的索引的int。 我猜y是一個邊界結構,因為您使用過

map.Add(y);

並且您的map的類型為List<bounds>

如果數據類型的目的是封裝一組固定的相關但獨立的值(例如點的坐標),則暴露域結構比任何其他數據類型都更符合該描述。 除了重寫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邊界並對其執行xmax -234. Any code which takes a都應為這些值做好准備,就像將這些字段作為四個單獨的參數一樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM