如何在1而不是0時在ArrayList
中啓動索引?有沒有辦法直接在代碼中做到這一點?如何創建一個起始索引爲1(而不是0)的ArrayList
(請注意,我要求ArrayList
,對於普通陣列請參閱Initializing an array on arbitrary starting index in c#)
如何在1而不是0時在ArrayList
中啓動索引?有沒有辦法直接在代碼中做到這一點?如何創建一個起始索引爲1(而不是0)的ArrayList
(請注意,我要求ArrayList
,對於普通陣列請參閱Initializing an array on arbitrary starting index in c#)
最明顯的方式做這將是包裹在自己實現一個ArrayList,並從所有操作索引減1使用該索引。
你實際上也可以在.NET中聲明一個數組,它有一個arbitrary lower bound(向下滾動到「使用非零下限創建數組」一節)。
這樣說的話,請不要在生產代碼中做。重要的是保持一致。
Stuff getValueAtOneBasedIndex(ArrayList<Stuff> list, index) {
return list.get(index -1);
}
嗯,你可以讓你自己:
public class MyArrayList<T> extends ArrayList<T> {
public T get(int index) {
super.get(index - 1);
}
public void set(int index, T value) {
super.set(index - 1, value);
}
}
但它引出了一個問題:爲什麼在地球上,你會這麼做呢?
正如其他答案所暗示的,有許多方法可以模擬這種情況,但沒有直接的方法可以在C#或其他常用的.NET語言中執行此操作。引用Eric Gunnerson:
的CLR不支持這種 結構的(我沒有使用 術語「滑稽」這裏...很難),但 有沒有,據我所知,任何 語言有內置語法到 這樣做。
我不知道它是否仍然存在,但是在某一時刻,Visual Basic會允許您使用Option Base 1
開始數組索引1。
在C#中,沒有一個System.Collections集合支持這一點,但您可以隨時編寫一個包裝類來爲您執行索引轉換。
真的,但應該避免這種情況。 VB的Option Base
創建了比解決更多的問題,我想象,因爲它打破了假設,並使事情更混亂。
這樣做的一個正當理由是編寫單元測試。某些第三方SDK(例如Excel COM互操作)期望您可以使用具有基於一個索引的數組。如果您正在使用這樣的SDK,那麼您可以並應該將此功能存入您的C#測試框架中。
下面應該工作:
object[,] comInteropArray = Array.CreateInstance(
typeof(object),
new int[] { 3, 5 },
new int[] { 1, 1 }) as object[,];
System.Diagnostics.Debug.Assert(
1 == comInteropArray.GetLowerBound(0),
"Does it look like a COM interop array?");
System.Diagnostics.Debug.Assert(
1 == comInteropArray.GetLowerBound(1),
"Does it still look like a COM interop array?");
我不知道是否有可能投這個作爲一個標準的C#風格的數組。可能不會。我也不知道乾淨的方式來硬編碼這樣一個數組的初始值,除了循環複製它們從一個標準的C#數組與硬編碼的初始值。在測試代碼中這些缺點都不應該是一個大問題。
我注意到我的評論適用於數組,而不是ArrayLists。哎呀。我希望使用Excel和VTSO的人仍然會發現它很有用,儘管它偏離了原來的問題。 – 2013-12-03 01:28:32
這裏是什麼我使用的是現在迅速VBA應用程序移植到C#:
它是一個數組類,從1開始接受多個維度。
雖然有一些額外的工作要做(IEnumerator的,等...),這是一個開端,就足以我,因爲我只使用索引。
public class OneBasedArray<T>
{
Array innerArray;
public OneBasedArray(params int[] lengths)
{
innerArray = Array.CreateInstance(typeof(T), lengths, Enumerable.Repeat<int>(1, lengths.Length).ToArray());
}
public T this[params int[] i]
{
get
{
return (T)innerArray.GetValue(i);
}
set
{
innerArray.SetValue(value, i);
}
}
}
首先,讓我通過解釋我的用例來說明這個答案:Excel Interop。使用數組讀取和寫入數據要容易得多,但Excel Range.Value2奇蹟般地返回基於1的對象數組。
所以,如果你正在寫到Excel,這就是你問的第一個地方這個問題的原因...那麼也許停止戰鬥,C#和讓Excel實例化數組你。因此,而不是:
object[,] newArray = new object[indexR, indexC];
您可以使用:
object[,] newArray = (object[,])RangeToWriteTo.Value2;
就我而言,我創建了一個包裝類,允許我使用一個數組,像這樣的屬性:
public abstract class ExcelRowBase
{
public object[,] data;
public ExcelRowBase(int index)
{
data = new object[2, index + 1];
}
}
public class InstanceRowModel : ExcelRowBase
{
public InstanceRowModel() : base(8)
{
//constructor unique to Wire Table
}
public object Configuration
{
get
{
return data[1, 1];
}
set
{
data[1, 1] = value;
}
}
...
因此,在所有情況下,我都是從相同的索引中讀取的。因此,爲了從模型轉換到一個Create方法,我只需要將這些屬性複製到使用從Excel創建的數組的模型中。
insertingModel.data = (object[,])writeRange.Value2;
//manually copying values from one array to the other
insertingModel.Configuration = model.Configuration;
...
writeRange.Value2 = insertingModel.data;
這適用於我現在,因爲我只需要在創建函數中執行此操作。在update/get/delete中,無論如何你都會得到基於Excel的數組。也許,未來的改善將是創建一個Excel範圍工廠,避免了0基於默認的建設都在一起,但這種解決方案只是給了我果嶺上我的測試,所以我感動了!
你爲什麼要? – Eric 2010-05-09 20:39:46
@Eric我說爲什麼,在我們大學的第一年,學生參加Pascal和這裏的索引從1開始,所以他們問他們是否可以做C#(只是一個問題)同樣的事情。 – 2010-05-09 20:44:44
0.5呢? :) – 2010-05-09 20:45:54