Почему C # не поддерживает перегрузку операторов с передачей по ссылке? - PullRequest
5 голосов
/ 31 октября 2009

Это ограничение CLR или решение о разработке языка? Я пытался сделать это в C ++ / CLI, конечно, где это работает, потому что нужно поддерживать нативный c ++:

public ref class Test
    {
        public:
        static Test^ operator &( Test^ msg, int& i )
        {
            i = i + 1;

            return nullptr;
        } 
    };

, а затем посмотрел на пропущенный компилятором вывод:

public: static Test __gc* op_BitwiseAnd(Test __gc* msg, Int32 __gc** modopt(IsImplicitlyDereferenced __gc*) i)
{
    i[0] += 1;
    return 0;
}

Я пошел дальше и попытался вызвать этот оператор из проекта C # - и, конечно, мне нужно было [небезопасно] сделать это (мне нужен указатель):

Test t = new Test();
int i = 0;

unsafe
{
    t = t & &i;
} 

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

Почему C # не может скрыть уродство за небезопасными и указателями, когда нам нужно иметь дело со ссылочными переменными в наших перегрузках операторов? Даже если бы я выбрал этот уродливый обходной путь, он не сработает в Silverlight, где небезопасные операции запрещены ...

Ответы [ 2 ]

5 голосов
/ 31 октября 2009

В C # ваши переменные никогда не изменяются вызываемыми пользователями, если вы явно не передадите их как ссылки (например, int.TryParse(s, out i), где вы явно указываете ключевое слово out). Эта функция усложнит ситуацию, если перегруженный оператор изменит содержание операндов без вашего явного разрешения.

Например,

public static MyStruct operator + (ref MyStruct left, ref MyStruct right) {
    left = new MyStruct(); // !!!!!!!!
    return something(left, right);
}

Когда вы ссылаетесь на такого оператора в C #:

MyStruct x = new MyStruct();
MyStruct y = new MyStruct();
MyStruct z = x + y; // in C#, you never expect `x` to be changed.
1 голос
/ 31 октября 2009

Я думаю, это потому, что оператор (в более математическом представлении, которое, похоже, принимает C #) - это логически то, что объединяет свои аргументы в новое значение, и никогда не должно ничего менять. C ++, похоже, рассматривает операторы скорее как версию общих операций с более удобным синтаксисом, чем функции, чем как способ представления математики в частности. Я думаю, что в C # вы почти никогда не увидите таких вещей, как определение операторов для потоковых операций и тому подобное.

...