C#-使其只允许同一实例修改其属性/调用方法?

C#-使其只允许同一实例修改其属性/调用方法?,c#,.net,lua,monogame,C#,.net,Lua,Monogame,我正在用MonoGame框架制作一个游戏引擎。由于这是一个多人游戏,其他玩家需要知道其他玩家的某些信息,例如位置和速度,通常用于AI反应 我将为玩家操作实现Lua脚本。然而,我目前还没有想到一种方法,这样玩家就不能修改其他玩家的信息,比如位置和名字 例如,假设我在C#中有以下属性: 看起来不错,对吧?不完全是。假设我有一个函数返回最近的敌人,名为GetNearestEnemy(),它返回另一个玩家。因为Player类可以访问自己的属性,所以我可以用其他方法轻松地执行类似的操作: public v

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

我将为玩家操作实现Lua脚本。然而,我目前还没有想到一种方法,这样玩家就不能修改其他玩家的信息,比如位置和名字

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

看起来不错,对吧?不完全是。假设我有一个函数返回最近的敌人,名为
GetNearestEnemy()
,它返回另一个玩家。因为Player类可以访问自己的属性,所以我可以用其他方法轻松地执行类似的操作:

public void DoStuff()
{
    Player otherPlayer = GetNearestEnemy();
    otherPlayer.Pos = new Vector2(34,151);
}
所以我想“也许我可以把实例作为参数传递。”

。。。并且总是把“这个”作为一个论点。然而,这也有同样的问题:我可以很容易地将
GetNearestEnemy()
传递给该方法,并且我可以设置敌人的位置

这是我试图阻止的行为类型。是否有一种方法可以更好地:

  • 获取调用该方法的实例
  • 在调用对象不知道的情况下从调用对象隐式设置参数
  • 或者有没有其他我看不到的方法呢?

    不幸的是,没有

    您想要的东西没有语言支持

    让我具体说明你想要什么,这样你才能理解我的回答

    你的问题基本上是这样的:假设我有一个对象的两个实例,并且这个对象中有一个私有setter的属性,那么有没有语言支持来确保实例1不能更改实例2的私有信息

    答案是否定的

    这将编译并“工作”:

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

    可以使用的访问修饰符有:

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

    除此之外,您没有其他选择。因此,“只有相同的实例才能访问此”不作为访问修饰符存在。

    这不起作用。如果
    Pos
    是一个带有私有setter(按原样)的属性,那么他们可以更改它的唯一方法就是从
    otherPlayer
    中调用公共方法。类似于
    otherPlayer.SetPos(新向量2(34151))
    ,其中
    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
    
    Player otherPlayer=GetNearestEnemy();
    
    otherPlayer.Pos=新矢量2(34151);// 发布的原始场景可以使用一个界面来处理,例如iperplayer,它只公开其他玩家应该看到的内容并隐藏其他属性(即其他属性不在iperplayer界面中。

    我不认为
    otherPlayer.Pos=new Vector2(34151)
    应该可以工作-你真的测试过它吗?不,这里没有语言支持来处理你想要的东西。大概,既然你在编写这个类,你就要确保它不会做不应该做的事情。@MetaColon是的。因为DoStuff是Player中的一个方法,它可以访问Player类所做的一切。让
    GetNearestEnemy
    返回源引用的克隆。这样,对克隆执行任何修改都将无法修改源引用。假设同一个程序员同时执行这两个类,这只是设计的一部分。如果有两个有竞争力的程序员,语言功能将无法阻止他们进行复制同一进程内的访问状态。但CLR具有一些隔离功能,如应用程序域(仅限完整的.NET Framework)。(请参阅.NET terrarium)因为DoStuff是Player中的一个方法,所以它可以访问Player类所做的一切。这就是我要说的。后者可以在类中完成,这是我不希望在该类的其他实例中发生的事情。好吧,这是一个令人不快的问题。经过一点思考,我想我应该做什么,而不是返回一个whol在这样的方法中,e player实例将返回一个结构,其中包含他们想要查看的值的只读副本。这样,脚本中的player对象可以从其他播放器获得他们想要的信息,但他们无法设置。感谢这些信息!您实际上可以通过闭包实现这一点,但您需要使用
    IDicti的一些变体例如expando对象。您没有类型系统支持,但可以使用闭包对实例级隐私进行建模。
    
    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