C # struct by-ref - PullRequest
       25

C # struct by-ref

1 голос
/ 09 января 2012

Есть ли способ в C # сделать это:

map.player.x = 5;

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

Для ясности:

  • Point - это структура, определяемая стандартными библиотеками C # /. Net и передаваемая по значению.
  • Создание класса-оболочки и реализация всех методов Point в качестве вызовов для Point - это долго и утомительно.
  • Наличие класса-обертки только с неявным прикрытием в / из Point не допустит вышеизложенного. Это должно быть записано как (Point)(map.player).x, что является неуклюжим.

Ответы [ 4 ]

6 голосов
/ 09 января 2012

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

Избегайте изменяемых структур (типов значений).struct Point - неудачный остаток старого Win32 API.

Так что стремитесь к map.player = new Point(5, map.player.y);

4 голосов
/ 09 января 2012

Нет.Либо player является переменной , и в этом случае вы не получаете никакой возможности проверить изменение во время назначения, либо player является свойством , и в этом случаевыражение map.player классифицируется как значение , и вам не разрешено устанавливать x часть (как это было бы бесполезно).

Я бы предложил вам создать метод,так что вы можете позвонить:

map.SetPlayerX(5);

... или сделать изменение значения x в более крупной операции, которой владеет класс Player.Скорее всего, это будет более ОО-подход - обычно , если вы захотите сделать что-то подобное, стоит взглянуть на дизайн и обязанности.

1 голос
/ 09 января 2012

Некоторые люди предлагают использовать тип класса для хранения значений X и Y. Я с подозрением отношусь к такому подходу и предположил бы, что во многих случаях семантика, полученная путем представления player как поля, была бы намного чище (хотя мне неясно, почему map имеет член с именем player. Если map является ссылкой на MapType, а экземпляр MapType имеет поле типа структуры player, с полем x типа integer, ясно, что изменение map.player.x повлияет на один экземпляр MapType. Также, сказав map1.player = map2.player;, вы скопируете поля из map2.player в map1.player. В отличие от этого, если бы player относился к типу класса, а один имел map1.player = map2.player; map1.player.x = 5;, это бы затронуло и map1, и map2.

Вопрос о том, следует ли использовать изменяемую структуру по сравнению с изменяемым классом, довольно прост, но понятие «если оно изменчиво, сделайте его классом» просто неверно. Просто спросите себя, учитывая:

  thing1 = thing2;
  thing1.x = 5;

хотите, чтобы второе утверждение влияло на значение thing2.x? Если да, используйте класс. Если нет, используйте структуру.

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

  public delegate ActionByRef<T>(ref T p);
  public delegate ActionByRef<T1,T2>(ref T1 p1, ref T2 p2);

  public void ActOnPlayer(ActionByRef<playerType&gt proc;)
  {
    proc(ref _player);
  }
  public void ActOnPlayer<T>(ActionByRef<playerType,T&gt proc, ref T param;)
  {
    proc(ref _player, ref param);
  }
... sample usage:
  map.ActOnPlayer((ref playerType it, ref int theParam) ->
    {it.x = theParam;}, someIntVariable);

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

1 голос
/ 09 января 2012

1

А как насчет назначения обеих координат одновременно?

map.player = new Point(5, 7);

Теперь вы можете иметь логику проверки внутри свойства проигрывателя.


2

Вам действительно нужно реализовать все элементы System.Drawing.Point?Не должно быть слишком сложно реализовать свою собственную версию только с теми вещами, которые вам действительно нужны.В Point.

не так много логики.
...