C# - 让它只有同一个实例可以修改它的 properties/call 方法?

C# - make it so only the same instance can modify its properties/call methods?

我正在使用 MonoGame 框架制作游戏引擎。由于这是一款多人游戏,其他玩家需要了解其他玩家的某些信息,例如位置和速度,通常用于 AI 反应。

我即将实施 Lua 玩家操作脚本。但是,我目前想不出有什么办法让玩家无法修改其他玩家的信息,例如位置和姓名。

例如,假设我在 C# 中有以下 属性:

public Vector2 Pos { get { return pos; } private set { this.pos = value; } }
private Vector2 pos;

看起来不错吧?好吧,不完全是。假设我有一个函数,returns 最近的敌人叫 GetNearestEnemy(),returns 另一个玩家。因为 Player class 可以访问它自己的属性,所以我可以用其他方法轻松地做这样的事情:

public void DoStuff()
{
    Player otherPlayer = GetNearestEnemy();
    otherPlayer.Pos = new Vector2(34,151);
}

所以我认为"maybe I could just pass the instance as a parameter."

public void SetPos(Player instance, Vector2 pos)
{
    if (instance != this)
        return;
    else
        this.pos = pos;
}

... 并始终将 "this" 作为参数传递。然而,这也有同样的问题:我可以很容易地将 GetNearestEnemy() 传递给该方法,并且我能够设置敌人的位置。

这是我试图阻止的行为类型。有没有办法最好:

  1. 获取调用方法的实例?
  2. 在调用对象不知情的情况下隐式设置参数?

或者有其他我没有看到的方法吗?

很遗憾没有。

没有您想要的语言支持。

让我具体说明您想要什么,以便您理解我的回答。

你的问题基本上是这样的:鉴于我有一个对象的 两个 个实例,并且我在这个对象中有一个私有 setter 的属性,是否有是否支持确保实例 #1 无法更改实例 #2 的私有信息的任何语言?

答案是否定的

这将编译并且 "work":

public class Test
{
    public void TestIt(Test t)
    {
        t.Value = 42;
    }

    public int Value
    {
        get;
        private set;
    }
}

...
var t1 = new Test();
var t2 = new Test();
t1.TestIt(t2); // will "happily" change t2.Value

基本上, 有责任确保这种情况不会发生,如果你不希望它发生的话。没有语言或运行时支持来防止这种情况。

您可以使用的访问修饰符是:

  • public:任何人都可以访问这个
  • private: 只有类型可以访问这个
  • protected:只有该类型或该类型的后代才能访问此
  • internal: 同一程序集中的任何类型都可以访问这个
  • internal protected:任何类型在同一个程序集的后代,都可以访问这个

除此之外,您别无选择。所以 "only the same instance can access this" 不作为访问修饰符存在。

那不行。如果 Pos 是一个带有私有 setter 的 属性(实际上),那么他们可以更改它的唯一方法是从 [=12= 中调用 public 方法].类似于 otherPlayer.SetPos(new Vector2(34,151)),其中 SetPos() 是:

public void SetPos(Vector2 NewPos)
    { Pos = NewPos; }

如果这是 属性 并且您担心被其他地方设置:

public Vector2 Pos { get { return pos; } private set { this.pos = value; } }
private Vector2 pos;

这行不通。所以你不用担心:

Player otherPlayer = GetNearestEnemy();
otherPlayer.Pos = new Vector2(34,151); // <--- no this will not work

属性 只能在 class 中设置。

发布的原始场景可以使用接口来处理,例如IPeerPlayer 只公开其他玩家应该看到的内容并隐藏其他属性(即其他属性不会出现在 IPeerPlayer 界面中。)