简体   繁体   中英

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

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.

您可以省略默认值,也可以在函数调用中声明T的类型

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

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 (ie 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM