也许我想要做的只是走错路。但我正在尝试编写游戏调试打印机的东西。它是以精灵字体为屏幕写入值,用于告诉调试器要关心的各种事情。我的调试器类很简单,但似乎在c#中的东西是通过值传递而不是引用。所以我转向ref关键字,如果我传入正确的数据类型,它似乎工作正常。问题是我有这个方法签名:
Dictionary<String, object> debugStrings = new Dictionary<String, object>();
...
...
public void addVariable(String index, ref object obj) //i think it needs to be a reference, not so sure though.
{
debugStrings.Add(index, obj);
}
这会在字典中添加一个变量,最终打印到屏幕上,并附带一个密钥,以便将其称为。</ p>
当我尝试使用上述方法时会出现问题:
debugPrinter.addVariable("myrotationvalue", ref this.Rotation);
根据评论中的链接,我将上面的代码更改为:
this.Rotation = 4;
object c = (object)this.Rotation;
this.Rotation = 20;
level.dbgd.addVariable("playerrot", ref c);
//always prints 4 out, i guess it still is not passing by reference?
因此它不会出错但总是打印出来4.不确定我将如何获得工作的参考。
再次对另一个编辑进行了参考:
this.Rotation = 20;
level.dbgd.addVariable("playerrot", this.Rotation);
this.Rotation = 4; //should draw to screen 4, doesn't draws 20
我显然这比我认为在打干草之前做一个简单的小有趣课程更难,哈哈哈......这对于即将到来的星期一来说并不好。
全班:
namespace GameGridTest.GameGridClasses.helpers
{
public class DebugDrawer : DrawableGameComponent
{
Dictionary<String, object> debugStrings = new Dictionary<String, object>();
int currentX;
int currentY;
VictoryGame _game;
private SpriteBatch spriteBatch;
private SpriteFont spriteFont;
public DebugDrawer(VictoryGame game) : base(game)
{
_game = game;
currentX = _game.Window.ClientBounds.Width - 400; //draw the debug stuff on right side of screen
currentY = 5;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteFont = _game.Content.Load<SpriteFont>("fonts\\helpers\\fpsFont");
}
public void addVariable<T>(String index, AbstractDebugHandler<T> obj) //i think it needs to be a reference, not so sure though.
{
debugStrings.Add(index, obj);
}
public void removeVariable(String index)
{
debugStrings.Remove(index);
}
protected override void UnloadContent()
{
_game.Content.Unload();
}
public override void Update(GameTime gameTime)
{
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
foreach (object obj in debugStrings) //draw all the values
{
spriteBatch.DrawString(spriteFont, obj.ToString(), new Vector2(currentX, currentY), Color.White);
currentY += 30;
}
currentY = 5;
spriteBatch.End();
}
}
public abstract class AbstractDebugHandler<T>
{
public AbstractDebugHandler(T obj)
{
InnerObject = obj;
}
public T InnerObject { get; private set; }
public abstract string GetDebugString();
}
public class ThisDebugHandler: AbstractDebugHandler<object>{
public ThisDebugHandler(object innerObject) : base(innerObject){
}
public override GetDebugString(){
return InnerObject.Rotation; //??
}
}
}
答案 0 :(得分:2)
您难以通过 引用并通过引用传递。
参数是按值传递的,但这并不意味着您无法传递引用类型。引用按值传递,这意味着引用被复制到堆栈,对象本身不会被复制。
当您必须更改要传入的变量时,将使用按引用传递。
只需删除ref
关键字,您的代码即可正常使用。
当您将值类型传递给方法时,它将被装箱,因此实际上会复制该值。您将显示值的副本,而不是实时值。通过引用传递参数也无济于事,因为您必须复制该值以使对象引用它。
如果要显示值类型,您宁愿发送一个可以检索值而不是值本身的函数:
Dictionary<String, Func<object>> debugStrings = new Dictionary<String, Func<object>>();
public void addVariable(String index, Func<object> getValue) {
debugStrings.Add(index, getValue);
}
用法:
debugPrinter.addVariable("myrotationvalue", () => this.Rotation);
答案 1 :(得分:1)
Ref将变量的指针赋给另一个Method,这意味着另一个方法可以设置变量的值,而不仅仅是使用指向对象的指针。这非常严重!看看下面的代码:
public void Test(){
object a = new object();
Test(a);
if(a==null)
Debug.WriteLine("isNull");
else
Debug.WriteLine("isSet");
}
public void Test2(ref object obj){
obj = null;
}
如果没有通过ref传递变量,您可以拥有相同的行为。在对象中包含valueTypes,以便可以存储指向对象的指针,而不是指向变量的指针。
例如:
public abstract class AbstractDebugHandler<T>{
public AbstractDebugHandler(T obj){
InnerObject = obj;
}
public T InnerObject {get; private set;}
public abstract string GetDebugString();
}
public void addVariable<T>(String index, DebugHandler<T> obj)
{
debugStrings.Add(index, obj);
//to get debugString use
string debugValue = obj.GetDebugString();
// will always geht the current Value of the defined Object
}
在你的情况下,你必须将“this”设置为innerObject,因为Rotation是一个ValueType,你必须传递包含ValueType的Object,所以方法“Debugger”和“callingMethod”都在处理同一个对象“这个”。 DebugHandler类现在可以处理字符串转换。参见
public class ThisDebugHandler: AbstractDebugHandler<ThisType>{
public ThisDebugHandler(ThisType innerObject) : base(innerObject){
}
public override GetDebugString(){
return InnerObject.Rotation;
}
}
因此,如果您现在调用您的调试方法,如:
public void MainMethod(){
this.Rotation = 4;
ThisDebugHandler handler = new ThisDebugHandler(this);
level.dbgd.addVariable<ThisType>("someIndex",handler );
this.Rotation = 20;
//level.dbgd.print();
// now prints 20
}
很乐意帮助您,所以请询问您是否还有其他问题