3

I would like to have a mapping function that does this:

public static void Map<T>(IEnumerable<T> src, params T[] dst)
{
    for (int i = 0; i < dst.Length; i++)
        dst[i] = src.ElementAt(i);
}

In order to make this work dst would also have to be declared as ref, which doesn't seem to be possible.

Here it is used in an imaginary unit test:

int a = 0, b = 0, c = 0;
int[] arr = { 1, 2, 3 };
Tools.Map(arr, a, b, c);
Assert.AreEqual(a, 1);
Assert.AreEqual(b, 2);
Assert.AreEqual(c, 3);

Is this possible at all? Does it already exist? Would it be a bad idea?

Edit: In other words, how do I give this implementation an arbitrary number of arguments:

public static void Map3<T>(IEnumerable<T> src, ref T a, ref T b, ref T c)
{
   a = src.ElementAt(0);
   b = src.ElementAt(1);
   c = src.ElementAt(2);
}
ndn
  • 33
  • 3
  • Yes, there are many bad things here, even before your bad idea ;p For starters, you are duplicating existing functionality. (`Enumerable.ToArray()`). – leppie Jun 25 '12 at 09:36
  • No. The conversion is not from IEnumerable to an Array but from IEnumerable to an arbitrary number of seperate variables. – ndn Jun 25 '12 at 09:42
  • Can't see how having the array as `ref` would make any difference. You are not assigning the actual array a new value in the function. – Magnus Jun 25 '12 at 09:45
  • 1
    @poingpoing: That makes no sense. – leppie Jun 25 '12 at 09:50
  • Also I would not recommend using `ElementAt`, depening on the underlying data type that can be a very costly operation. If you need to access by index take in `IList` instead. – Magnus Jun 25 '12 at 09:54
  • @Magnus: Thanks, but none of your comments is on topic. – ndn Jun 25 '12 at 10:20

1 Answers1

4

You can't do that. Params is a convenience by the C# compiler, which just creates an array on the spot, and populates it with the arguments.

Since an array cannot contain "ref" variables, neither can you pass "ref" to params in this way.

You are looking for something like "multiple assignment" which some languages have. If it existed, it would work something like this:

my (a,b,c,d) = enumerable.ToArray();

See : C#: Split string and assign result to multiple string variables

You might consider a set of extension methods:

public static void ReadValues<T>(this T[] array, ref T t0){
   t0 = array[0];
}
public static void ReadValues<T>(this T[] array, ref T t0, ref T t1){
   t0 = array[0];
   t1 = array[1];
}

and so on, up to as many parameters as you want to support.

It's not an arbitrary number, but 20 should be high enough for most purposes. And hey, if it isn't, just go higher.

Then you can use it like this:

enumerable.ToArray().ReadValues(var1, var2, var3);    

You could even combine this with Slice to read arbitrary entries:

// reads indexes 3 to 7
enumerable.ToArray().Slice(3,4).ReadValues(var1, var2,var3,var4); 

See slicing here:

Community
  • 1
  • 1
Ben
  • 34,935
  • 6
  • 74
  • 113
  • You are correct. Actually, I am just looking for a convenient way of assigning variables. – ndn Jun 25 '12 at 09:56
  • After your edits this is the perfect answer. I was looking to avoid writing out t0 = arr[0] ... tn = arr[n] but ok. Thank you. – ndn Jun 25 '12 at 10:23