C #: я должен использовать или ref, чтобы получить эту структуру обратно? - PullRequest
4 голосов
/ 03 апреля 2011

Я не уверен, как лучше задать этот вопрос, поэтому начну с примера:

public static void ConvertPoint(ref Point point, View fromView, View toView) {
    //Convert Point
}

Этот вызов рекурсивный.Вы передаете точку, она преобразует ее относительно fromView в относительную значение toView (если один является предком другого).

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

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

Это может быть запутанный вопрос, и мне нужно еще больше путаницы, пока я в нем, должен ли я сохранить временный статический Point экземпляр для быстрых преобразований или было бы так же просто создать новую точкувсякий раз, когда вызывается этот метод (он называется лот )?

Ответы [ 5 ]

8 голосов
/ 03 апреля 2011

Беспокойство по сборщику мусора никогда не является ошибкой, когда имеешь дело с недолговечными объектами, такими как Point, предполагая, что это действительно класс.Учитывая, что это C #, он, вероятно, будет структурой, не превышающей 16 байт.В этом случае вы должны всегда написать метод для возврата Point.Это оптимизируется во время выполнения, структура вписывается в регистры процессора.

Только когда-либо рассматривайте передающие структуры по ref, когда они большие.

1 голос
/ 03 апреля 2011

Структуры должны быть неизменяемыми, поэтому я бы проголосовал за возвращение точки, отличной от метода. Если вам нужна изменчивость, то вы должны сделать это классом и создать метод класса для его преобразования. Побочным продуктом последнего может быть изменение рекурсивного спуска в итеративное применение преобразований.

1 голос
/ 03 апреля 2011

Зависит от того, что вы делаете и почему вы это делаете.

Структуры в C # не похожи на классы в Java вообще . Они как примитивные типы с точки зрения скорости и семантики. (На самом деле, примитивные типы в некотором смысле являются структурами). Их передача на самом деле бесплатна, поэтому, если это оптимизирует что-то, что не является проблемой, я предлагаю вам просто вернуть метод Point.

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

Обратите внимание, например, что в библиотеке Microsoft XNA структура Matrix имеет две версии одного и того же метода:

static void CreateLookAt(
ref Vector3 cameraPosition, ref Vector3 cameraTarget, ref Vector3 cameraUpVector,
    out Matrix result)

static Matrix CreateLookAt(
    Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector)

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

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

1 голос
/ 03 апреля 2011

Я склонен делать все в классе, чтобы упростить вещи. Если вы обнаружите, что это создает нежелательную нагрузку на память только в вашем приложении, тогда вы должны исследовать решение, которое включает изменчивую структуру.

Причина, по которой я говорю это, состоит в том, что GC имеет тенденцию очень хорошо оптимизировать коллекции в соответствии с потребностями вашего приложения, а изменяемые структуры являются печально известной головной болью. Не вводите эту головную боль, если GC может справиться с давлением памяти нескольких объектов.

0 голосов
/ 03 апреля 2011

Поскольку точка является структурой, я не вижу преимуществ в использовании ref здесь.В любом случае, он будет скопирован в стек несколько раз, так почему бы просто не вернуть его?Я думаю, что это сделает код более читабельным, если вы объявите этот метод с Point в качестве возвращаемого типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...