Ian
Ian

Reputation: 30813

Passing by reference to n-th element in C#

In C, if we have an array, we can pass it by reference to a function. We can also use simple addition of (n-1) to pass the reference starting from n-th element of the array like this:

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]);
}

Resulting in these:

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.

In C#, we can also pass reference to an object by ref (or, out). The object includes array, which is the whole array (or at least, this is how I suppose it works). But how are we to pass by reference to the n-th element of the array such that internal to the function, there is only string[] whose elements are one less than the original string[] without the need to create new array?

Must we use unsafe? I am looking for a solution (if possible) without unsafe

Edit:

I understand that we could pass Array in C# without ref keyword. Perhaps my question sounds quite misleading by mentioning ref when we talk about Array. The point why I put ref there, I should rather put it this way: is the ref keyword can be used, say, to pass the reference to n-th element of the array as much as C does other than passing reference to any object (without mentioning the n-th element or something alike)? My apology for any misunderstanding occurs by my question's phrasing.

Upvotes: 3

Views: 1676

Answers (5)

Voodu
Voodu

Reputation: 782

Question is old, but maybe answer will be useful for someone. As of C# 7.2 there are much more types to use in that case, ex. Span or Memory.
They allow exactly for the thing you mentioned in your question (and much more).
Here's great article about them

Currently, if you want to use them, remeber to add <LangVersion>7.2</LangVersion> in .csproj file of your project to use C# 7.2 features

Upvotes: 0

Yves
Yves

Reputation: 3902

Edit:

You won't be able to do it as you do in C in safe code.

A C# array (i.e. string[]) is derived from abstract type Array. It is not only a simple memory block as it is in C.

So you can't send one of it's element's reference and start iterate from there.


But there are some solutions which will give you the same taste of course (without unsafe):

Like:

  • As @Chris mentioned you can use ArraySegment<T>.
  • As Array is also an IEnumerable<T> you can use .Skip and send the returned value. (but this will give you an IEnumerable<T> instead of an Array). But it will allow you iterate.
  • etc...

Upvotes: 3

B.Balamanigandan
B.Balamanigandan

Reputation: 4875

Your confusion is a very common one. The essential point is realizing that "reference types" and "passing by reference" (ref keyboard) are totally independent. In this specific case, since string[] is a reference type (as are all arrays), it means the object is not copied when you pass it around, hence you are always referring to the same object.

Modified Version of C# Code:

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

Upvotes: 0

Ren&#233; Vogt
Ren&#233; Vogt

Reputation: 43886

If the method should only read from the array, you can use linq:

string[] strings = {"str1", "str2", "str3", ...."str10"};
print(strings.Skip(1).Take(4).ToArray());

Upvotes: 0

Chris Shain
Chris Shain

Reputation: 51339

The "safe" approach would be to pass an ArraySegment struct instead.

You can of course pass a pointer to a character using unsafe c#, but then you need to worry about buffer overruns.

Incidentally, an Array in C# is (usually) allocated on the heap, so passing it normally (without ref) doesn't mean copying the array- it's still a reference that is passed (just a new one).

Upvotes: 3

Related Questions