【问题标题】:Storing a reference to an outside variable within an object在对象中存储对外部变量的引用
【发布时间】:2012-07-27 06:11:54
【问题描述】:

我正在为 XNA 中的游戏编程,并尝试创建一个通用数学对象,并在构建期间提供存储的输出位置。

我的计划是在构造函数中使用 ref,但我不确定如何在初始调用之后将该引用保存/存储在对象中...

public MathObject(ref float OutParam)
{
    Out = OutParam; // This obviously won't do what I want... But it's where I'd like to do it.
}

在更新中,我想说明输入并让产品修改存储的输出位置:

foreach (MathObject MatOb in MathList)
{
    MatOb.Update(time);
}

我们的想法是创建一个模块化数学工具,以在整个代码中使用,并在创建时将其定向到其他地方的预先存在的对象参数(“输出”),它将在更新中修改(无需重新引用)。希望这将允许一个循环来指导工具的每个实例来修改它的给定输出。

据我了解,在 c++ 中,这可以通过将要修改的参数的地址存储在数学对象中,然后在更新中使用它来指向和修改该位置的内存。

在不使用不安全代码的情况下,在 c# 中是否可能发生类似的事情?

是否应该始终避免使用不安全的代码?

编辑:

-- 预期用途--

我希望能够创建具有可调节“设置并忘记”输出位置的对象。

例如,我构建了一个在游戏界面中工作的简单贝塞尔曲线编辑器。我可以在代码中设置输出位置,以便给定曲线始终调整特定参数(例如字符位置),但也可以在界面内修改输出连接的内容。

特定应用程序主要用于游戏内编辑。我知道编辑器在独立时是最实用的,但这将是有限的,游戏控制台友好的编辑功能(不太强大,但原则上类似于 Little Big Planet 的编辑功能)。

我的背景是 3D 设计和动画,因此我习惯于使用许多基于节点的编辑系统 - 创建各种实用节点并调整输入和输出以驱动着色、装配模型等参数。我当然会没有尝试在游戏中重新创建它,但我很好奇将某些原则延续并应用于有限的游戏内编辑功能。只是排除故障最好去做。

感谢您的回复!

【问题讨论】:

  • 一旦有人在同一个句子中说出 "universal""object" 这两个词,我很确定您提出的设计是在处理并发的情况下不安全(这在游戏中很常见,如果这就是您使用 XNA 的原因)。我不清楚你在用这个数学对象做什么以及为什么它需要是通用的。您能否进一步解释一下“为什么”?
  • 我在问题中添加了一部分关于我的思路是什么。

标签: c# xna


【解决方案1】:

在 C# 中执行此操作的方法是使用一对 get/set 委托。你可以使用这个方便的辅助结构来存储它们:

public struct Ref<T>
{
    Func<T> get;
    Action<T> set;

    public Ref(Func<T> get, Action<T> set)
    {
        this.get = get;
        this.set = set;
    }

    public T Value { get { return get(); } set { set(value); } }
}

给定这样的类:

class Foo { public float bar; }

像这样使用它:

Foo myFoo = new Foo();
Ref<float> barRef = new Ref<float>(() => myFoo.bar, (v) => myFoo.bar = v);

// Ta-Da:
barRef.Value = 12.5f;
Console.WriteLine(barRef.Value);

(请注意,我还没有实际测试过这里的代码。这个概念很有效,而且我之前已经成功使用过它,但是我可能会因为在脑海中输入这个而弄乱了我的语法。)

因为这个问题是用XNA标记的,所以我应该简单谈谈性能:

  1. 您可能会发现它的执行速度比等效的内存访问慢一个数量级左右 - 因此它不适合紧密循环。

  2. 创建这些东西会分配内存。由于多种原因,这对性能非常不利。所以避免在你的绘制/更新循环中创建这些。不过,在加载过程中很好。

最后,这比简单地直接访问属性更难看 - 所以请确保你正在尽你所能避免在可能的情况下使用它。

【讨论】:

  • 谢谢,很有帮助。我一直在研究 deligates,但仍然在他们周围环绕着我的头。看起来他们将是要走的路。我肯定会避免在更新中使用它们。干杯!
【解决方案2】:

如果没有不安全的代码,我不知道如何在 C# 中执行此操作,但是.. 如果您绝对必须使用此解决方案解决您的问题并且不使用不安全的代码,那么也许 memory mapped files 是您的朋友。即便如此,这些在 .NET 4.0 之前还没有用于 .NET 开发,我不确定这个选项与不安全代码的性能相比如何。

【讨论】:

    【解决方案3】:

    我想你需要什么is the observer design pattern。对数学对象的更新感兴趣的项目将注册 avent(即MathObjectChange)并做出适当的反应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      相关资源
      最近更新 更多