【问题标题】:c# accessing struct members within class' methodsc# 在类的方法中访问结构成员
【发布时间】:2015-05-06 11:34:27
【问题描述】:

我正在尝试编写一个简单的游戏。我想设计一个“运动控制器”对象,它可以处理来自引擎的移动指令。我还希望该对象公开一个方法,该方法将检查其状态并返回真/假,具体取决于它是否准备好移动。状态将保存为一组布尔变量。由于它们很多,我决定将它们组合在一个名为“flags”的新结构中。这或多或少是这样的:

public class movContr
{
    int movId;
    public struct flags
    {
        bool isMoving;
        bool isLocked;
        bool isReady;
        (...)
    }

    public bool CheckReadiness()
    {
        if(flags.isReady==true) return true;
        return false;
    }
}

现在的问题是这不会编译,错误是:

error CS0120: An object reference is required to access non-static member

违规行是:

if(flags.isReady==true) return true;

所以我猜 C# 不会将结构视为仅包含顺序变量的内存 blob,而是将其视为类的一些“特殊”表亲。

这是我的问题:

我应该如何处理访问结构类成员的方法?如何在类方法中引用其未来实例的成员?我尝试了这个:

if(this.flags.isReady==true) return true;

但我得到了同样的错误。

或者,如果使用 'struct' 封装我的标志变量不是正确的做法,那是什么?

我试图自己找到答案,但由于我能想到的所有关键字都非常通用,因此结果也是如此。大多数处理静态成员,这不是这里的解决方案,因为我需要 movContr 类的多个独立实例。

【问题讨论】:

  • 我不确定你是否需要一个结构体。看起来您可以为该结构中的每个字段在您的类上创建属性或字段。
  • 不敢相信它这么简单,抱歉我不能接受多个答案:( 有时候我觉得我应该坚持我发誓@juharr的汇编程序,因为这是很早的舞台和我的记忆力真的很差我想尽可能保持它的可读性以防我需要从项目中休息一下到 movContrObj.flags.isMoving,至少现在是这样
  • 就我个人而言,我发现这里使用结构的可读性较差,但如果您对它更满意,那么就没有任何真正的伤害。

标签: c# struct member non-static


【解决方案1】:

您已经创建了一个名为flags 的结构声明。 但这只是声明,而不是具体的价值。所以,sn-p

if(flags.isReady==true) return true;

尝试访问静态成员 (https://msdn.microsoft.com/en-us/library/98f28cdx.aspx)。

您需要声明该类型的变量才能使用它:

private flags myFlag;

public bool CheckReadiness()
{
     if(myFlag.isReady==true) return true;
      return false;
}

也许您的困惑来自 C++,其中允许“内联、匿名”结构:

struct {
    int some_var
} flags;

flags.some_var = 1;

在 C# 中不可用

【讨论】:

  • 我来自较低级别的背景,使用诸如运算符重载之类的东西有时仍然会使我的脚踝肿胀:) 也就是说,如果我解决了所有的怪癖,像 C# 这样的语言似乎非常适合编写脚本游戏之类的(虽然不确定它在性能方面的表现如何)
【解决方案2】:

你不能使用flags,因为你只是用“struct flags”声明一个数据类型。您需要创建一个实例。

并且您应该将结构的字段声明为公共的。否则您将无法访问它们。

    int movId;

    // Delace fields as public
    public struct flags
    {
        public bool isMoving;
        public bool isLocked;
        public bool isReady;
    }

    // create a instance
    private flags myFlag;

    public bool CheckReadiness()
    {
        if(this.myFlag.isMoving == true) return true;
        return false;
    }

    // Better Implementation
    public bool CheckReadiness()
    {
        if (this.myFlag.isMoving) return true;
        return false;
    }

    // Best Implementation
    public bool CheckReadiness()
    {
        return (this.myFlag.isMoving);
    }

【讨论】:

    【解决方案3】:

    拥有属性可能更有意义,而不是创建结构。

    public class movContr
    {
        int movId;
    
        public bool IsMoving { get; set; }
        public bool IsLocked { get; set; }
        public bool IsReady { get; set; }
            (...)
    }
    

    那么您只需调用IsReady,而不是调用CheckReadiness

    var temp = new movContr();
    if(temp.IsReady)
    {
        // It is ready.
    }
    

    【讨论】:

    • 现在说得通了,但是稍后检查准备情况可能会占用 CPU 的资源,而且无论如何我都需要缓存的值,所以它不会一遍又一遍地执行
    • Auto 属性只是用于支持字段的 getter 和 setter 方法的简写。不确定与从结构返回值的方法相比,这将如何增加 CPU 的负载。在这两种情况下,被访问的值都在堆栈中。
    • 我的意思是,现在 CheckReadiness() 只检查 isReady 的值,但希望在不久的将来它也会包含一些复杂的计算。所以我最好只在真的需要的时候调用 CheckReadiness(),它的结果会被缓存在 isReady 中,以供以后廉价访问。
    【解决方案4】:

    正如异常所暗示的,您需要创建如下所示的击中实例:-

    flags flag;
    flag.isReady = true;
    

    更多信息:-

    http://www.dotnetperls.com/struct

    请注意,在 Main 中,结构是如何在堆栈上创建的。 没有使用“新”关键字。它被用作值类型,例如 int。

    顺便说一句,如果这是代码中显示的唯一用途,我建议您使用 自动实现的属性 而不是 Struck

    参考:-https://msdn.microsoft.com/en-us/library/bb384054.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-31
      • 2023-03-22
      • 2022-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      相关资源
      最近更新 更多