如何在C#中从静态方法调用非静态方法?

94

我有以下的代码,我想在 data2() 中调用 data1()。 在C#中可以吗? 如果是,应该怎么做?

private void data1()
{
}
private static void data2()
{
   data1(); //generates error
}

2
尽管下面的所有答案都不成立:你真的做不到那样的事情。 - TaW
11个回答

145

您需要创建该类的一个实例并在其上调用该方法。

public class Foo
{
    public void Data1()
    {
    }

    public static void Data2()
    {
         Foo foo = new Foo();
         foo.Data1();
    }
}

3
如果这个方法是在ASP页面内的,该怎么办呢?我目前正在为此苦苦挣扎。不能手动创建一个ASP页面实例,那么我该如何从静态方法(WebMethod)调用ASP页面内的方法呢? - Dean Martin
4
@ReidGarwin 看起来把行为封装在页面内并试图从其他地方调用它是很错误的。也许应该将其重构回另一个类,并在需要时作为 Page 实例的依赖项。不过,说实话,整个模式都在呼喊着有问题,即使可能,我也会尽量避免使用它。 - tvanfosson
这是一个具有欺骗性的解决方案:只要Data1依赖于实例数据,它就不会真正奏效。如果Data1不依赖于实例数据,为什么不将其设置为静态? - TaW

28

也许您正在寻找的是单例模式(Singleton pattern)?

public class Singleton
{
    private Singleton() {}

    public void DoWork()
    { 
        // do something
    }

    // You can call this static method which calls the singleton instance method.
    public static void DoSomeWork()
    { 
        Instance.DoWork();
    }

    public static Singleton Instance
    {
        get { return instance; } 
    }

    private static Singleton instance = new Singleton();
}

您仍然需要创建类的一个实例,但您可以确保只有一个实例。


1
当我读到他的问题时,我的第一反应也是+1。 - AaronLS
4
单例模式本质上是全局数据——它使你的代码难以测试(类与单例耦合)并且(如果可变)难以调试。尽可能避免使用它们(以及静态方法)。如果需要的话,可以考虑使用 DI/IoC 容器库来代替。 - TrueWill

25

你需要在静态方法中创建该类的一个实例,然后调用它。

例如像这样:

public class MyClass
{
   private void data1()
   {
   }
   private static void data2()
   {
     MyClass c = new MyClass();
     c.data1();
   }
}

12

如果你想调用一个非静态方法,首先必须创建其父类的实例。

因此,在静态方法中,你需要实例化一个新的对象...

Vehicle myCar = new Vehicle();

...然后调用非静态方法。

myCar.Drive();

11

您只需要提供对象引用。请在位置中提供您的类名。

private static void data2()
{
    <classname> c1 = new <classname>();
    c1. data1();
}

7

对于非常老的帖子回答表示抱歉,但我相信我的答案可能有助于其他人。

通过使用委托(delegate)可以实现同样的事情。

public class MyClass
{
    private static Action NonStaticDelegate;

    public void NonStaticMethod()
    {
        Console.WriteLine("Non-Static!");
    }

    public static void CaptureDelegate()
    {
        MyClass temp = new MyClass();
        MyClass.NonStaticDelegate = new Action(temp.NonStaticMethod);
    }

    public static void RunNonStaticMethod()
    {
        if (MyClass.NonStaticDelegate != null)
        {
            // This will run the non-static method.
            //  Note that you still needed to create an instance beforehand
            MyClass.NonStaticDelegate();
        }
    }
}

1
你可以这样使用call方法:Foo.Data2()
public class Foo
{
    private static Foo _Instance;

    private Foo()
    {
    }

    public static Foo GetInstance()
    {
        if (_Instance == null)
            _Instance = new Foo();
        return _Instance;
    }

    protected void Data1()
    {
    }

    public static void Data2()
    {
        GetInstance().Data1();
    }
}

1
 new Foo();
 Foo.StaticMethod();

class Foo
{
    private static Foo foo;

    public Foo()
    {
        foo = this;
    }

    private void PrintHello()
    {
        Console.WriteLine("Hello");
    }

    public static void StaticMethod()
    {
        foo.PrintHello();
    }
}

4
你需要先实例化它。https://dotnetfiddle.net/yRQuaE - trinalbadger587

0

请问,我认为对您的问题的回答可能是:

public class <Classname> {
    static method() {
        (new <Classname>)->non-static();
    }

    non-static method(){ ...; }

    ~<Classname>(){...;}

};

当数据成员被声明为静态时,该类的所有对象只维护一个数据副本。静态成员具有或处理永久存储。

对于C++和可能的C#,当使用new运算符时,它会为类对象分配内存,内存分配后调用对象构造函数。因此,由于静态成员是在其所属类名之前调用的,与非静态成员相同,因此使用(new Classname)似乎像是调用具有预定义永久存储的成员,如静态数据成员。

因此,这种方法存在一个不便之处:无法释放调用非静态方法分配的内存,因为没有保存对它的访问;每次调用需要该非静态方法的静态方法时,都会分配内存,而在其过程结束时没有可释放的访问。

为解决这个问题,该类必须有一个析构函数来释放每个过程分配的内存。您还可以使用终结器。

参考文献

https://learn.microsoft.com/en-us/cpp/cpp/static-members-cpp?view=msvc-170

https://learn.microsoft.com/en-us/cpp/cpp/new-operator-cpp?view=msvc-170

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/finalizers


希望这些细节能对您有所帮助。



1
目前你的回答不够清晰。请编辑并添加更多细节,以帮助其他人理解它如何回答所提出的问题。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

-1

静态方法不允许直接调用非静态方法。

原因:静态方法仅属于其类,而不属于任何对象或实例。

因此,当您尝试从同一类中的静态方法访问任何非静态方法时,您将收到:

"需要对象引用才能访问非静态字段、方法或属性"。

解决方案:只需声明一个引用,如下所示:

public class <classname>
{
static method()
{
   new <classname>.non-static();
}

non-static method()
{

}


}

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