一个对象引用需要用于非静态字段、方法或属性。

3

我知道之前已经有人问过这个问题,但是那些场景都太具体了,我对基础概念感到困惑。

我有两个基本版本的C#程序,一个可以工作,另一个不行。如果有人能够解释一下为什么在第二个程序中会出现需要非静态字段、方法或属性的对象引用的错误,我会很感激。

可以工作的版本:

namespace Experiments
{
    class Test
    {
        public string myTest = "Gobbledigook";

        public void Print()
        {
            Console.Write(myTest);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test newTest = new Test();
            newTest.Print();
            while (true)
                ;
        }
    }
}

无法工作:

namespace Experiments
{
    class Test
    {
        public string myTest = "Gobbledigook";

        public void Print()
        {
            Console.Write(myTest);
        }
    }

    class Program
    {
        public Test newTest = new Test();

        static void Main(string[] args)
        {
            newTest.Print();
            while (true)
                ;
        }
    }
}

当我尝试从第二个程序的Test()类打印文本时,它会给出错误需要对象引用来访问非静态字段、方法或属性,我不明白为什么会这样。我可以看到它与我声明Test()类的实例的位置有关,但我不记得在C++中发生过这样的事情,所以它让我感到困惑。
发生了什么?
2个回答

4

问题不在于类的定义,而在于关键字static的使用。

Test类的newTest对象是Program类的公共成员,而mainProgram类中的静态函数。错误信息An object reference is required for the non-static method明确提到了这一点。所以你需要将newTest对象声明为静态的,以便在像main这样的静态方法中访问它们。

像这样:

 public static Test newTest = new Test();

附加说明

请考虑您正在定义方法Print,并将其作为静态方法放在类Test中,如下所示:

 public static void Print()
 {
    Console.Write(myTest);
 }

那么你不能像你当前使用的方式一样调用方法(newTest.Print();)。相反,你必须使用Test.Print();,因为静态成员不能通过实例引用。相反,它是通过类型名称引用的。例如,考虑以下类


创建静态变量不是一个好的实践,除非在特殊情况下,就像…… - Simflare
继续之前的讨论 - 就像在C++中不鼓励使用全局变量一样? - Simflare
我不认为使用静态变量是一种糟糕的做法,如果需要可以使用。但是在Web应用程序中我不喜欢使用静态变量,因为它们具有应用程序范围。 - sujith karivelil
好的。非常感谢,你帮了我很多 :) - Simflare
1
这个答案并不是一个很好的“为什么”的解释。它讲解了如何解决错误,但并没有解释错误的原因。错误信息中没有“清楚”地提到任何内容。该错误会让你认为某处缺少引用(具体指哪里也说不清),而不是该方法应该是静态的。 - dsanchez

1
在第一个程序中,你创建了一个新的实例并放在了一个静态方法里。在这个方法内部做任何事情都没问题。
但是当你想要调用一些方法或者访问一些非静态变量时,你需要它们成为静态的。原因是当你调用一个静态方法时,类的实例没有被创建,因此非静态变量的实例也没有被创建,你无法访问它们!
所以,在第二个程序中,只有在你有一些代码行在Program类之外时,如Program p = new Program();,才会执行newTest变量初始化行。解决方案是将变量设置为静态,以便在静态Print()方法之外访问它,或者将Min()方法转换为非静态模式,这对于Main()方法是不可能的。
如果你想定义一个全局变量,我建议你定义一个特殊的类,例如MyGlobals:
public class SomeClass
{
    public int x;
}

public class MyGlobals
{
    public static SomeClass mySharedVariable = new SomeClass();

    public SomeClass myGlobalVariable = null;
}

// Usage:
class Program
{
    static void Main(string[] args)
    {
        MyGlobals.mySharedVariable.x = 10; // Shared among all instances
        MyGlobals myGlobal = new MyGlobals(); // New instance of MyGlobals
        myGlobal.myGlobalVariable = new SomeClass(); // New instance of SomeClass
        myGlobal.myGlobalVariable.x = 10; // One instance of MyGlobals including one instance of SomeClass
    }
}

谢谢,这是一个有帮助的解释。在C++中,这与我习惯使用的static关键字有些不同。然而,创建静态变量是否被鼓励,就像全局变量在C++中被反对一样呢? - Simflare
我编辑了我的答案,展示了在C#中定义全局变量的一些方法。请再次检查我的答案。希望对你有用。 - Amin
谢谢您抽出时间分享这个 :) - Simflare

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接