Подтвердить что ты не робот

Невозможно использовать ref и out для первого параметра ("this") в методах расширения?

Почему запрещается вызывать Extension Method с помощью модификатора ref?

Это возможно:

public static void Change(ref TestClass testClass, TestClass testClass2)
{
    testClass = testClass2;
}

И это не одно:

public static void ChangeWithExtensionMethod(this ref TestClass testClass, TestClass testClass2)
{
    testClass = testClass2;
}

Но почему?

4b9b3361

Ответ 1

Вы должны явно указать ref и out. Как вы это сделаете с помощью метода расширения? Более того, вы действительно хотите?

TestClass x = new TestClass();
(ref x).ChangeWithExtensionMethod(otherTestClass);
// And now x has changed?

Или вы не хотите указывать часть ref только для первого параметра в методах расширения?

Это просто звучит странно для меня, если честно, и рецепт для нечитаемого (или, по крайней мере, трудно предсказанного) кода.

Ответ 2

Я согласен с ответами от Jon Skeet et al. о том, как разрешить методы "ref this" расширения могут сделать код более неясным. Но если вы посмотрите на некоторые пространства имен в .Net Framework, для метода, вызываемого в структуре, это является обычным.

Возьмем, к примеру, структуры System.Drawing(Point, Rectangle и т.д.). Каждый из них имеет методы (например, Offset, Inflate и т.д.), Которые сами мутируют структуру. Я не говорю, что это хорошая идея, на самом деле мне лично очень неприятно, что Offset, Inflate и т.д. Мутируют сами структуры, вместо того, чтобы возвращать новые, и я знаю, что некоторые из вас выступают против идеи изменчивых структур в вообще.

Я сомневаюсь, что есть случаи, когда вызов метода ссылочного типа изменяет ссылку (если только она не имеет класс String, где я могу себе представить, что может быть какая-то магия компилятора для переключения ссылок на интернирование и т.д.), Поэтому имеет смысл запретить использование этого ссылки для ссылочных типов, поскольку изменение ссылки будет полностью нестандартным побочным эффектом вызова метода.

Но в отношении структур, позволяющих "этот ref" не будет значительно уменьшать читаемость кода больше, чем Rectangle.Inflate и т.д., и это будет единственным средством "имитировать" такое поведение с помощью функции расширения.

Как примечание, вот один пример, где "этот ref" может быть полезен, и IMHO все еще читаем:

void SwapWith<T>(this ref T x, ref T y) {
   T tmp = x; x = y; y = tmp;
}

Ответ 3

Я согласен, что это полезно для struct

Поэтому я хочу предложить это для создания метода расширения для struct. это ключевое слово должно всегда передавать struct по ссылке

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

Ответ 4

В С# 7.2 вы можете использовать методы расширения ref

Ответ 5

Это означало бы, что вызов myObject.ChangeWithExtentionMethod(otherObject) действительно имел бы потенциал для изменения значения myObject. IMO, который не будет делать для очень читаемого кода, когда вы можете вместо этого добиться желаемого эффекта, используя обычный метод без расширения с помощью ссылки.

EDIT: Моя точка зрения, вызов метода должен требовать от вас использовать ключевое слово ref в любое время, когда вы передаете что-то по ссылке. Использование ref с использованием метода расширения 'this' нарушит это поведение.

Ответ 6

не совсем верно, вы можете использовать ref в методах расширения только в С# 7.2, если это структура. https://github.com/dotnet/csharplang/issues/186