Как мне получить доступ к «этому» из метода расширения С#?

Я работал с Vector2 и XNA и обнаружил, что вызов функции-члена Normalize() для нулевого вектора нормализует его до вектора {NaN, NaN}. Это все хорошо, но в моем случае я бы предпочел оставить их как Zero Vectors.

Добавление этого кода в мой проект позволило использовать симпатичный метод расширения:

using ExtensionMethods;

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static Vector2 NormalizeOrZero(this Vector2 v2)
        {
            if (v2 != Vector2.Zero)
                v2.Normalize();
            return v2;
        }
    }
}

К сожалению, этот метод возвращает нормализованный вектор, а не просто нормализует вектор, который я использую для вызова этого метода расширения. Вместо этого я хотел бы вести себя как vector2Instance.Normalize().

Помимо того, что это недействительно, как мне настроить это так, чтобы «v2» был изменен? (По сути, мне нужен доступ к «этому» объекту или мне нужно, чтобы «v2» передавался по ссылке.)

Редактировать:

И да, я пробовал это:

    public static void NormalizeOrZero(this Vector2 v2)
    {
        if (v2 != Vector2.Zero)
            v2.Normalize();
    }

Не работает, v2 — это просто переменная в области действия NormalizeOrZero.


person Jude Allred    schedule 20.11.2008    source источник


Ответы (4)


Это не работает, потому что Vector 2 на самом деле является структурой. . Это означает, что он передается по значению, и вы не можете изменить копию вызывающего объекта. Я думаю, что лучшее, что вы можете сделать, это обходной путь, указанный lomaxxx.

Это иллюстрирует, почему обычно следует избегать использования структур. См. этот вопрос для получения дополнительной информации. Vector2 нарушает правило, согласно которому структуры должны быть неизменяемыми, но, вероятно, это имело смысл в контексте XNA.

person Daniel Plaisted    schedule 20.11.2008

Что ж, если вы действительно умираете от этого, вы можете сделать что-то вроде этого:

public static void NormalizeOrZero(this Vector2 ignore, ref Vector2 v2)
{
    if (v2 != Vector2.Zero)
        v2.Normalize();
}

Вы бы назвали это так:

v2.NormalizeOrZero(ref v2);

Это очень уродливо, но это сработает, чего бы оно ни стоило. Но в этот момент вы также можете вызвать статический метод в первую очередь.

person Ryan Lundy    schedule 20.11.2008

Я не уверен, почему ваш второй пример кода не работает, но если первая часть кода делает то, что вы хотите, вы можете просто обойти это, перейдя:

Vector2 v2 = new Vector2()
v2 = v2.NormalizeOrZero();
person lomaxx    schedule 20.11.2008
comment
Второй пример кода изменяет копию структуры, поэтому, хотя он работает в некотором смысле, он не делает то, что хочет OP, и изменяет вызывающий объект. - person Servy; 03.04.2013

Вам понадобятся как модификатор ref, так и модификатор this в аргументе, что вряд ли сработает.

person yfeldblum    schedule 20.11.2008