2013-03-22 2 views
2

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

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

public class Ability: Buffable 
    { 

     public string abbr { get; private set; } 

     public Ability(string name, string abbr, uint score) : base(name, score) 
     { 
      this.abbr = abbr; 
     } 

     // Ability Modifier 
     // returns the ability modifier for the class. 
     public int Ability_modifier() 
     { 
      const double ARBITARY_MINUS_TEN = -10; 
      const double HALVE = 2; 
      double value = (double)this.Evaluate(); 
      double result = (value + ARBITARY_MINUS_TEN)/HALVE; 

      // Round down in case of odd negative modifier 
      if (result < 0 && ((value % 2) != 0)) 
      { 
       result--; 
      } 
      return (int)result; 
     } 

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

Есть ли какая-нибудь работа, чтобы сделать это или альтернативный способ подойти к этой проблеме, что мой указатель заразил ум не рассматривает? Я бы предпочел не передавать способность к функции, которая каждый раз оценивает навык, так как тот, который ссылается, никогда не изменяется после строительства.

ответ

3

Очевидная проблема с тем, что, по-видимому, сохранение ссылок является табу в C#.

Абсолютно нет. Ссылки хранятся повсеместно. Вы делаете это здесь, например:

this.abbr = abbr; 

System.String класс, и поэтому ссылочный тип. И поэтому значение abbr является ссылкой.

Я сильно подозреваю, что вы неправильно поняли, как работают ссылочные типы в C#. Если вы помните ссылку на объект, то изменения объекта будут видны через ссылку. Однако изменений в исходном выражении , которое вы скопировали, не будет.

Например, используя StringBuilder как удобный изменяемом ссылочный тип:

StringBuilder x = new StringBuilder("abc"); 

// Copy the reference... 
StringBuilder y = x; 

// This changes data within the object that x's value refers to 
x.Append("def"); 

// This changes the value of x to refer to a different StringBuilder 
x = new StringBuilder("ghi"); 

Console.WriteLine(y); // abcdef 

Смотрите мои статьи на references and values и parameter passing in C# гораздо более подробно.

+0

Спасибо, я определенно не понимал, как это сработало. Статьи были весьма полезными. – stygma

-1

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

+4

Нет, объекты не передаются по ссылке - ссылки передаются по значению (по умолчанию). Для параметров 'ref' есть * real * pass by reference, который может быть применен к параметрам либо ссылочных типов, либо типов значений. –

+0

Это зависит от вашего определения термина «пройти по ссылке», что является разумно спорным. Одним из полезных определений, которые я часто видел, является то, что «если функция изменяет значение, при передаче по ссылке модификации появляются также в пределах функции вызова, которые они не выполняют при передаче по значению». По этому определению любой ссылочный тип C# будет «передаваться по ссылке», а не «по значению». Передача «ссылки по значению» в C++ использовала бы указатель, который для разработчика C++ равняется «передаче по ссылке». –

+0

Нет, это связано с изменением значения параметра. Изменение самого параметра (например, 'builder = new StringBuilder()') не будет отображаться вызывающему. Будет замечено изменение данных внутри объекта, на которое ссылается значение параметра (например, 'builder.Append (« Foo »)), но это не * изменяет значение самого параметра. Значение параметра является только ссылкой, и после этого ссылка будет одинаковой. Я действительно не думаю, что здесь есть какие-то дебаты, - спецификация языка довольно ясна. –

0

Я недостаточно разбираюсь в коде, чтобы дать конкретный пример, но для этого нужно передать делегат лямбды, такой как () => object.property, вместо этого: object.property.

+0

Я думаю, что вы отвечаете на более продвинутый вопрос, чем тот, который ставит ОП. Эрик обеспечивает общую реализацию вашего предложения [здесь] (http://stackoverflow.com/a/4543089/18192). – Brian

+0

@Brian: Я хорошо знаю это сообщение; За последние месяцы я несколько раз сталкивался с этим. Однако мое чтение сообщения заключается в том, что OP хочет передать средство пересчета свойства, а не текущее значение свойства; мое предложение - это средство для этого. –

Смежные вопросы