-2

Need to convert some c++ code into c#. In this case I need to pass in the second dimension of a multidimensional array into the function dot(...).

This is the original c++ declaration /* and definition */, followed by the global static const array.

double dot( const int* g, const double x, const double y ) /*{ return g[0]*x + g[1]*y; }*/;
static const int grad3[ 12 ][ 3 ] = {...};

In c# it could be this:

public class TestClass
{
    float dot( ref int[] g, float x, float y ) { return g[0] * x + g[1] * y; }
    public static readonly int[,] grad3 = new int[12, 3]{...};
}

Here is an example to see how it should be accessed:

public class TestClass
{
    ...
    void test()
    {
        int gi0 = 0;
        double d1 = dot( grad3[ gi0 ], x0, y0, z0 );
    }
}
Tim
  • 101
  • 9

1 Answers1

0

You can pass a portion of your array without using ref.

My suggested example is not a multi-dimensional array but is a jagged array which is an array of arrays.

public class TestClass
{
    public static float Dot(int[] g, float x, float y) 
    { 
        return g[0] * x + g[1] * y; 
    }

    // Note that the second index is empty
    public static readonly int[][] grad3 = new int[12][] {...};
}

You can pass your multi dimensional array (jagged array) like this:

var value = TestClass.grad3;
TestClass.Dot(value[0], x0, y0, z0);

Also, initialization syntax is like this:

public static readonly int[][] TwoDimArray = new int[3][]
{
    new[] {1, 2, 3},
    new[] {4, 5, 6},
    new[] {8, 9, 10}
};

Comparison between jagged arrays and multi-dimensional arrays:

public static double Sum(double[,] d) {
    double sum = 0;
    int l1 = d.GetLength(0);
    int l2 = d.GetLength(1);
    for (int i = 0; i < l1; ++i)
        for (int j = 0; j < l2; ++j)
            sum += d[i, j];
    return sum;
}

// This is intuitive and clear for me
public static double Sum(double[][] d) {
    double sum = 0;
    for (int i = 0; i < d.Length; ++i)
        for (int j = 0; j < d[i].Length; ++j)
            sum += d[i][j];
    return sum;
}
ndogac
  • 1,185
  • 6
  • 15
  • Is there a specific reason why multidimensional arrays aren't used often, should it be avoided? – Tim Oct 02 '20 at 22:00
  • To fix that generalization, I don't use them very much because working with jagged arrays are more convenient and they are faster, and they seem more intuitive for me to work with, see my updated code sample. – ndogac Oct 02 '20 at 22:06
  • Arrays are not passed by reference, and `ref` is not redundant. The value of the variable is a reference, which is very different than being passed by reference. Also the assertion that multidimensional arrays aren't used just isn't true, they're used plenty. You personally may not use them, but that's not the same thing. – Servy Oct 02 '20 at 22:44
  • @Servy I fixed that statement that I don't use them frequently and I find them more intuitive to work with, did you just read my comment? – ndogac Oct 02 '20 at 22:49
  • @Servy Also, arrays are reference types and reference types are always passed by reference. I know that of course the value of the reference will be passed. But generally, everyone uses *passed by reference* term. – ndogac Oct 02 '20 at 22:51
  • In addition, `ref` is redundant in his case, because he wants to pass a portion of his multi-dim array - conceptually, don't try to fix this too :) – ndogac Oct 02 '20 at 22:52
  • @N.Dogac You haven't edited your answer in 43 minutes, so no, you haven't fixed it to address any of those points. As for the comment, saying that they're faster just isn't true, each have situations where they're advantageous over the other (although in many situations either is sufficient as the differences are not often large). Saying you like them is fine, saying they're rare in C# in general and that *everyone* uses jagged arrays instead is not. – Servy Oct 02 '20 at 22:52
  • Read this, they are faster. https://stackoverflow.com/questions/468832/why-are-multi-dimensional-arrays-in-net-slower-than-normal-arrays – ndogac Oct 02 '20 at 22:53
  • @N.Dogac No, arrays *aren't* passed by reference. Yes, lots of people say that, but it's an objectively false statement to make. Passing a reference by value and passing a value by reference *behave differently*, so using the proper terminology is important, else people believing that will find their programs not behaving as they expect without them knowing why. You can put `g = new int[5];` into your first method as an example of the difference between a parameter passed by reference and by value. – Servy Oct 02 '20 at 22:55
  • @Servy I agree with you in using the proper terminology, I fixed my statement about saying "*multi-dimensional arrays are not used too much*" and "*arrays are passed by reference*". Thank you for your correction. – ndogac Oct 02 '20 at 22:57
  • @N.Dogac That's a demonstration of *one particular use case*. That's not a demonstration that it's faster *in all situations*. You're comparing the difference between performing one arithmetic operation vs. resolving the value of a reference to it's value an additional time. They'll be pretty similar if the reference is in the CPU cache already, and slower if it's not. In that example nothing but the array is being used, so it never leaves the cache. It also uses more memory (often not in a way that matters, but it's technically a difference). – Servy Oct 02 '20 at 22:57
  • `GetLength` is a virtual function, and it will be dispatched dynamically, you can look at the IL and generated assembly. In many cases, multi-dimensional arrays generate much more code than jagged arrays. This is just one argument that it being slower than jagged arrays, there are many others. – ndogac Oct 02 '20 at 23:07
  • In C/C++ too, *pass by reference* means the value of the pointer is copied to the function. So everything is *pass by copy*. But most people uses *passed by reference* term because it is easier to understand and it is conceptually true. – ndogac Oct 02 '20 at 23:11
  • @ndogac Like I said, certain operations on each type of array are slower than the other. Neither is *universally better*, as you claim. They each have their pros and cons and situations where they are the most suitable. Additionally lines of code is not a good metric for measuring the performance of an operation. Operations lots of code an be fast, operations with few lines of code can be slow. What that code does is what matters. – Servy Oct 03 '20 at 00:16
  • @ndogac In C++ pass by reference means that you're using the `&` operator, which is approximately the same semantics as as when using the `ref` or `out` keywords in C#. Likewise, in C++ when you pass a pointer *without* that operator (which is semantically the same as a reference type in C# without `ref` or `out`) you don't say that you're "passing the parameter by reference", you say you're passing a pointer by value. The distinction is *just as important* in C++ as it is in C# for exactly the same reasons, and using the improper term is just as confusing and misleading. – Servy Oct 03 '20 at 00:25