один из параметров бинарного оператора должен быть содержащим тип c#

public static int[,] operator *(int[,] arr1, int[,] arr2)
    {
        int sum;
        int[,] res = new int[arr1.GetLength(0), arr2.GetLength(1)];
        for (int i = 0; i < arr1.GetLength(0); i++)
        {
            for (int j = 0; j < arr2.GetLength(1); j++)
            {
                sum = 0;
                for (int k = 0; k < arr1.GetLength(1); k++)
                {
                    sum = sum + (arr1[i, k] * arr2[k, j]);
                }
                res[i, j] = sum;
                //Console.Write("{0} ", res[i, j]);
            }
            //Console.WriteLine();
        }

        return res;
    }

Здесь я пытаюсь перегрузить оператор * для умножения двух матриц... но компилятор продолжает показывать мне ошибку, которая...

"один из параметров бинарного оператора должен быть содержащим тип С#"

пожалуйста, скажите мне, в чем проблема в моем коде и как ее решить..


person Siladitya    schedule 02.07.2016    source источник
comment
Компилятор говорит вам именно о проблеме - вам не разрешено перегружать произвольные операторы подобным образом... вы можете перегружать только операторы, где один из операндов (или возвращаемый тип для преобразования) является типом, в котором вы находитесь. объявление оператора   -  person Jon Skeet    schedule 02.07.2016
comment
Должен признаться, что поначалу я был озадачен тем, что OP исходил из C++ (подумайте о бесплатных функциях). Но обнаружил, что С# не такой разрешительный, как С++.   -  person mireazma    schedule 09.01.2018


Ответы (1)


Компилятор уже говорит вам, что не так, но процитирую раздел 7.3.2 спецификации C# 5:

Объявления определяемых пользователем операторов всегда требуют, чтобы по крайней мере один из параметров имел тип класса или структуры, который содержит объявление оператора. Таким образом, пользовательский оператор не может иметь ту же подпись, что и предопределенный оператор.

Другими словами, было бы неплохо иметь:

class Foo
{
    public static int[,] operator *(int[,] arr1, Foo arr2)
    {
        ...
    }
}

... потому что тогда второй операнд является объявляющим типом. Но в вашем случае оба операнда int[,].

Вместо этого вы могли бы добавить метод расширения:

public static class ArrayExtensions
{
    public static int[,] Times(this int[,] arr1, int[,] arr2)
    {
        ...
    }
}

Тогда вы могли бы:

int[,] x = ...;
int[,] y = ...;
int[,] z = x.Times(y);

Другим решением - лучшим, IMO, было бы объявить свой собственный класс Matrix для инкапсуляции матричных операций. Затем вы можете определить свой собственный оператор умножения:

public static Matrix operator *(Matrix left, Matrix right)

... и вы не вмешиваетесь в массивы int[,], которые не предназначены для обработки как матрицы.

person Jon Skeet    schedule 02.07.2016
comment
Я пришел сюда именно за этим ответом, но, честно говоря, легко прочитать ошибку, поскольку она думает, что ни arr1, ни arr2 не являются int[,] (содержащим типом). Теперь я понимаю, что это значит, но я бы сказал, что компилятор точно НЕ говорит, в чем заключается реальная проблема, с какой-либо ясностью. arr1 и arr2 ОБА содержат тип: int[,]. - person Jesse Williams; 12.12.2018
comment
@JesseWilliams: лично я думаю, что достаточно ясно, что содержащий тип — это тип, содержащий оператор, который не является int[,]. Каким образом int[,] является содержащим типом в этом случае? - person Jon Skeet; 12.12.2018
comment
Это имеет смысл, как только вы это поймете - легко понять это неправильно. Очевидно, что Containing относится к классу, в котором в данный момент находится объявление. Но, по крайней мере, в свете того, как обычно записываются эти ошибки, легко увидеть, что это относится к возвращаемому типу, а не к родительскому классу. Да, если бы они имели в виду тип возврата, они бы сказали тип возврата - я согласен. Но что-то, что вы обычно не делаете, может быть неправильно понято. /shrug Достаточно легко решить. - person Jesse Williams; 12.12.2018