通过引用传递到 C# 中的第 n 个元素
Passing by reference to n-th element in C#
在 C 中,如果我们有一个数组,我们可以通过引用将它传递给一个函数。我们还可以使用简单的 (n-1)
相加来传递从数组的第 n
个元素开始的引用,如下所示:
char *strArr[5];
char *str1 = "I want that!\n";
char *str2 = "I want this!\n";
char *str3 = "I want those!\n";
char *str4 = "I want these!\n";
char *str5 = "I want them!\n";
strArr[0] = str1;
strArr[1] = str2;
strArr[2] = str3;
strArr[3] = str4;
strArr[4] = str5;
printPartially(strArr + 1, 4); //we can pass like this to start printing from 2nd element
....
void printPartially(char** strArrPart, char size){
int i;
for (i = 0; i < size; ++i)
printf(strArrPart[i]);
}
导致这些:
I want this!
I want those!
I want these!
I want them!
Process returned 0 (0x0) execution time : 0.006 s
Press any key to continue.
在 C# 中,我们还可以通过 ref
(或 out
)传递对 object
的引用。该对象包括数组,它是 whole 数组(或者至少,我认为它是这样工作的)。但是我们如何通过引用传递数组的第 n
个元素,使得在函数内部,只有 string[]
其元素比原始 string[]
少一个而不需要创建新数组吗?
我们必须使用unsafe
吗?我正在寻找没有 unsafe
的解决方案(如果可能的话)
编辑:
我知道我们可以在没有 ref
关键字的情况下在 C# 中传递 Array
。当我们谈论 Array
时,提及 ref
可能听起来很误导我的问题。为什么我把 ref
放在那里,我应该这样说:是否可以使用 ref
关键字,比如说,将引用传递给数组的第 n
个元素除了传递对任何 object
的引用(不提及第 n
元素或类似的东西)之外,C 所做的一样多吗?对于我问题的措辞造成的任何误解,我深表歉意。
"safe" 方法是传递一个 ArraySegment 结构。
您当然可以使用不安全的 c# 传递指向字符的指针,但是您需要担心缓冲区溢出。
顺便说一句,C# 中的数组(通常)分配在堆上,因此正常传递它(没有引用)并不意味着复制数组 - 它仍然是传递的引用(只是一个新引用)。
编辑:
您将无法像在 安全 代码中使用 C 那样执行此操作。
C# 数组(即 string[]
)派生自抽象类型 Array
。
它不仅仅是一个简单的内存块,因为它在 C.
所以您不能发送其中一个元素的引用并从那里开始迭代。
但是有一些解决方案当然会给你相同的味道(没有 unsafe):
喜欢:
- 如@Chris 所述,您可以使用
ArraySegment<T>
.
- 由于
Array
也是一个 IEnumerable<T>
,您可以使用 .Skip
并发送返回值。 (但这会给你一个 IEnumerable<T>
而不是 Array
)。但它会让你迭代。
- 等...
你的困惑很常见。要点是要意识到 "reference types" 和 "passing by reference"(参考键盘)是完全独立的。在这种特定情况下,由于 string[] 是引用类型(所有数组也是),这意味着当您传递对象时不会复制该对象,因此您总是引用同一个对象。
C# 代码的修改版本:
string[] strArr = new string[5];
strArr[0] = "I want that!\n";
strArr[1] = "I want this!\n";
strArr[2] = "I want those!\n";
strArr[3] = "I want these!\n";
strArr[4] = "I want them!\n";
printPartially(strArr.Skip(1).Take(4).ToArray());
void printPartially(string[] strArr)
{
foreach (string str in strArr)
{
Console.WriteLine(str);
}
}
如果该方法只应从数组中读取,您可以使用 linq:
string[] strings = {"str1", "str2", "str3", ...."str10"};
print(strings.Skip(1).Take(4).ToArray());
问题很旧,但也许答案对某人有用。
从 C# 7.2 开始,在这种情况下可以使用更多类型,例如。 Span or Memory.
他们完全允许您在问题中提到的事情(以及更多)。
Here's great article about them
目前,如果你想使用它们,记得在你的项目的 .csproj 文件中添加 <LangVersion>7.2</LangVersion>
以使用 C# 7.2 特性
在 C 中,如果我们有一个数组,我们可以通过引用将它传递给一个函数。我们还可以使用简单的 (n-1)
相加来传递从数组的第 n
个元素开始的引用,如下所示:
char *strArr[5];
char *str1 = "I want that!\n";
char *str2 = "I want this!\n";
char *str3 = "I want those!\n";
char *str4 = "I want these!\n";
char *str5 = "I want them!\n";
strArr[0] = str1;
strArr[1] = str2;
strArr[2] = str3;
strArr[3] = str4;
strArr[4] = str5;
printPartially(strArr + 1, 4); //we can pass like this to start printing from 2nd element
....
void printPartially(char** strArrPart, char size){
int i;
for (i = 0; i < size; ++i)
printf(strArrPart[i]);
}
导致这些:
I want this!
I want those!
I want these!
I want them!
Process returned 0 (0x0) execution time : 0.006 s
Press any key to continue.
在 C# 中,我们还可以通过 ref
(或 out
)传递对 object
的引用。该对象包括数组,它是 whole 数组(或者至少,我认为它是这样工作的)。但是我们如何通过引用传递数组的第 n
个元素,使得在函数内部,只有 string[]
其元素比原始 string[]
少一个而不需要创建新数组吗?
我们必须使用unsafe
吗?我正在寻找没有 unsafe
编辑:
我知道我们可以在没有 ref
关键字的情况下在 C# 中传递 Array
。当我们谈论 Array
时,提及 ref
可能听起来很误导我的问题。为什么我把 ref
放在那里,我应该这样说:是否可以使用 ref
关键字,比如说,将引用传递给数组的第 n
个元素除了传递对任何 object
的引用(不提及第 n
元素或类似的东西)之外,C 所做的一样多吗?对于我问题的措辞造成的任何误解,我深表歉意。
"safe" 方法是传递一个 ArraySegment 结构。
您当然可以使用不安全的 c# 传递指向字符的指针,但是您需要担心缓冲区溢出。
顺便说一句,C# 中的数组(通常)分配在堆上,因此正常传递它(没有引用)并不意味着复制数组 - 它仍然是传递的引用(只是一个新引用)。
编辑:
您将无法像在 安全 代码中使用 C 那样执行此操作。
C# 数组(即 string[]
)派生自抽象类型 Array
。
它不仅仅是一个简单的内存块,因为它在 C.
所以您不能发送其中一个元素的引用并从那里开始迭代。
但是有一些解决方案当然会给你相同的味道(没有 unsafe):
喜欢:
- 如@Chris 所述,您可以使用
ArraySegment<T>
. - 由于
Array
也是一个IEnumerable<T>
,您可以使用.Skip
并发送返回值。 (但这会给你一个IEnumerable<T>
而不是Array
)。但它会让你迭代。 - 等...
你的困惑很常见。要点是要意识到 "reference types" 和 "passing by reference"(参考键盘)是完全独立的。在这种特定情况下,由于 string[] 是引用类型(所有数组也是),这意味着当您传递对象时不会复制该对象,因此您总是引用同一个对象。
C# 代码的修改版本:
string[] strArr = new string[5];
strArr[0] = "I want that!\n";
strArr[1] = "I want this!\n";
strArr[2] = "I want those!\n";
strArr[3] = "I want these!\n";
strArr[4] = "I want them!\n";
printPartially(strArr.Skip(1).Take(4).ToArray());
void printPartially(string[] strArr)
{
foreach (string str in strArr)
{
Console.WriteLine(str);
}
}
如果该方法只应从数组中读取,您可以使用 linq:
string[] strings = {"str1", "str2", "str3", ...."str10"};
print(strings.Skip(1).Take(4).ToArray());
问题很旧,但也许答案对某人有用。
从 C# 7.2 开始,在这种情况下可以使用更多类型,例如。 Span or Memory.
他们完全允许您在问题中提到的事情(以及更多)。
Here's great article about them
目前,如果你想使用它们,记得在你的项目的 .csproj 文件中添加 <LangVersion>7.2</LangVersion>
以使用 C# 7.2 特性