How to write overloaded generic extension methods for T[], T[][] without ambiguity?
Asked Answered
H

3

5

I want to write extension methods for converting a vector and matrix into string. I did this in the following way.

For Vector

public static string GetString<T>(this T[] SourceMatrix, string ColumnDelimiter = " ")
{
    try
    {
        string result = "";
        for (int i = 0; i < SourceMatrix.GetLength(0); i++)
            result += SourceMatrix[i] + ColumnDelimiter;
        return result;
    }
    catch (Exception ee) { return null; }
}

For Matrix

public static string GetString<T>(this T[][] SourceMatrix, string ColumnDelimiter = " ", string RowDelimiter = "\n")
{
    try
    {
        string result = "";
        for (int i = 0; i < SourceMatrix.GetLength(0); i++)
        {
            for (int j = 0; j < SourceMatrix[i].GetLength(0); j++)
                result += SourceMatrix[i][j] + "" + ColumnDelimiter;
            result += "" + RowDelimiter;
        }
        return result;
    }
    catch (Exception ee) { return null; }
}

Now i am using following code which causes ambiguity.

List<double[]> Patterns= GetPatterns(); 
Patterns.ToArray().GetString();

Error

Error   5   The call is ambiguous between the following methods or properties: 
'MatrixMathLib.MatrixMath.GetString<double[]>(double[][], string)' and 
'MatrixMathLib.MatrixMath.GetString<double>(double[][], string, string)'    

Can anyone suggest me to write these extension methods correctly.

Thanks in advance.

Hanafee answered 3/8, 2014 at 8:36 Comment(4)
just a small suggestion, the is already the static string method (string.Join(<delimiter>,<array>)) to convert an array to stringCroteau
Storing a matrix in a jagged array is odd... Why not use a multi-dimensional one?Choirboy
@BadikAli String.Join is not a extension method, it is a static method of string class.Theaterintheround
@Choirboy as i mentioned in the code actually i am using List<double[]> and using ToArray() extension which will return double[][], any way in my problem i need jagged array as each row(pattern) can have different no.of values.Hanafee
J
4

There is nothing wrong with your methods. It is the compiler that can't choose between them.

As you can see in the error message, the compiler could assume T to be double[] and match the first method, or double and match the second one. This will be solved by explicitly mentioning which method you want to use:

Patterns.ToArray().GetString<double>();
Jacquijacquie answered 3/8, 2014 at 9:0 Comment(5)
perhaps a little late?Tilbury
Come on Mitch. there is no rep for a late answer, so it's just a good deed!Jacquijacquie
@MitchWheat: (Edit: This was to your now-deleted comment.) Uhm, actually, unlike you, he actually answered the question when he said the compiler can't distinguish between them. You just answered an entirely different question without ever stating whether or not the task as requested was even possible, leaving the OP hanging in midair. +1 for Alireza.Digamma
@MitchWheat: Maybe you should start giving it a little more then.Digamma
@MitchWheat Will it help if I delete my answer? A few reps are not worth it anyway.Jacquijacquie
S
4

You can either omit the default values or state the type of T in the function call

Superpower answered 3/8, 2014 at 8:40 Comment(0)
J
4

There is nothing wrong with your methods. It is the compiler that can't choose between them.

As you can see in the error message, the compiler could assume T to be double[] and match the first method, or double and match the second one. This will be solved by explicitly mentioning which method you want to use:

Patterns.ToArray().GetString<double>();
Jacquijacquie answered 3/8, 2014 at 9:0 Comment(5)
perhaps a little late?Tilbury
Come on Mitch. there is no rep for a late answer, so it's just a good deed!Jacquijacquie
@MitchWheat: (Edit: This was to your now-deleted comment.) Uhm, actually, unlike you, he actually answered the question when he said the compiler can't distinguish between them. You just answered an entirely different question without ever stating whether or not the task as requested was even possible, leaving the OP hanging in midair. +1 for Alireza.Digamma
@MitchWheat: Maybe you should start giving it a little more then.Digamma
@MitchWheat Will it help if I delete my answer? A few reps are not worth it anyway.Jacquijacquie
S
0

The compiler can't tell whether you want to call GetString<double[]> or GetString<double> because both methods fit the invocation.

The easiest way to solve that is to simply change one of the names (i.e. GetArrayString<T>). A better solution IMO is to have only 1 method that solves both cases like this one:

public static string Join<T>(this T[] sourceMatrix, string columnDelimiter = " ", string rowDelimiter = "\n")
{
    if (sourceMatrix.Length == 0)
    {
        return string.Empty;
    }

    if (sourceMatrix[0] as Array == null)
    {
        return string.Join(columnDelimiter, sourceMatrix);
    }

    var rows = new List<string>();
    foreach (T item in sourceMatrix)
    {
        var array = item as Array;
        var row = "";
        for (int j = 0; j < array.GetLength(0); j++)
            row += array.GetValue(j) + columnDelimiter;
        rows.Add(row);
    }

    return string.Join(rowDelimiter, rows);
}

Usage:

int[] a = {1, 2, 3};
int[] b = { 1, 2, 4 };
int[][] c = {a, b};

Console.WriteLine(a.Join());
Console.WriteLine();
Console.WriteLine(c.Join());

Output:

1 2 3

1 2 3
1 2 4

Note: This only solves for 1-2 dimensions, but can easily be generalized to n dimensions.

Slaveholder answered 3/8, 2014 at 9:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.