如何在c#中创建一个索引从1开始的一维数组
本文关键字:索引 一个 开始 一维数组 创建 | 更新日期: 2023-09-27 17:52:17
用于多维数组。CreateInstance可以用来创建基于索引的非零数组,但是如果你尝试创建一维数组(向量),例如:
public double[] myArray = (double[])Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });
当从多维数组强制转换为单维数组失败时,这将在运行时失败
"Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'"
现在我可以创建一个零基数组并忽略第一个值,或者使用偏移量等,但我是否忽略了一些c#语法魔法,允许非零基向量?
更新:
我相信Eric Lippert的话,如果他说"在c#中没有明显的方法来创建非从零开始的数组"
您可以在c#中创建非从零开始的数组,但是使用它有点令人讨厌。它绝对不是普通数组(即从零开始的一维数组)的简单替代品。
// Create the array.
Array myArray = Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });
// Fill the array with random values.
Random rand = new Random();
for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
{
myArray.SetValue(rand.NextDouble(), index);
}
// Display the values.
for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
{
Console.WriteLine("myArray[{0}] = {1}", index, myArray.GetValue(index));
}
为此所需的GetValue/SetValue语法比每次从vector索引中减去1更难看。
如果值类型存储在数组中,那么它将像在常规数组中一样存储在连续位置,但是getter和setter将需要将值装箱(除非有一些我不知道的编译器魔法)。getter通常需要强制类型转换(只是为了让它更难看)。
double myValue = (double)myArray.GetValue(index);
还注意GetUpperBound
的正确比较是<=
,不像Length
是与<
比较。
基于非零的数组确实存在于C中,并且有一种方法可以创建一个基于1的(或任何)数组。
我完全同意它们是混乱的,它们不应该用于除了遗留的东西之外的任何东西,但是它们对于与旧的COM库交互是必不可少的。
最常见的情况是使用Excel库中的Microsoft.Office.Interop.Excel.Range对象,该对象仍然使用旧的DCOM接口。
的例子:
/// <summary>
/// Makes the equivalent of a local Excel range that can be populated
/// without leaving .net
/// </summary>
/// <param name="iRows">number of rows in the table</param>
/// <param name="iCols">number of columns in the table</param>
/// <returns>a 1's based, 2 dimensional object array which can put back to Excel in one DCOM call.</returns>
public static object[,] NewObjectArray(int iRows, int iCols)
{
int[] aiLowerBounds = new int[] { 1, 1 };
int[] aiLengths = new int[] { iRows, iCols};
return (object[,])Array.CreateInstance(typeof(object), aiLengths, aiLowerBounds);
}
在本例中,需要此代码的原因是对excel的每个DCOM调用都是一个跨进程调用,如果要一次访问一个单元格,则会产生巨大的开销(检索或设置值)。Excel范围是一个基于1的二维数组,如果创建了这个数组,并在本地填充它,它可以在一个跨进程调用中被推送到Excel中,从而产生巨大的性能改进。
如果有人还在寻找一个基于一维的数组实现,这里是一个一维通用的基于一维的数组,它只是一个常规数组的包装类型:
https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Enumerable/OneBased/OneBasedArray.cs也有一个二维版本,但还没有更高维度的版本(这段代码是为了支持Excel而写的,所以2D就足够了):
https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Enumerable/OneBased/OneBasedArray2D.cs这两种类型都在相同的repo下的相关测试项目中为它们编写了测试:
https://github.com/ColmBhandal/CsharpExtras/tree/master/CsharpExtrasTest/OneBased免责声明:这些repos托管在我的个人GitHub帐户上,并且是开源的。
c#中的所有数组都是从零开始的。据我所知,没有办法创建一个基于1的数组。想象一下,如果这是可能的,会发生什么样的混乱。下面是一个类似的线程,它更详细地解释了这个问题——c#:非基于零的数组不符合cls