一个非静态类中的静态方法有什么意义?

45
我很难理解下面代码中潜在的错误:
class myClass
{
    public void print(string mess)
    {
        Console.WriteLine(mess);
    }
}

class myOtherClass
{
    public static void print(string mess)
    {
        Console.WriteLine(mess);
    }
}

public static class Test
{
    public static void Main()
    {
        myClass mc = new myClass();
        mc.print("hello");

        myOtherClass moc = new myOtherClass();
        moc.print("vhhhat?"); 
       //This says I can't access static method in non static context, but am I not?

    }
}

我无法想象为什么会在非静态类中声明静态方法,所以为什么.NET不会抛出异常错误。

此外,

moc.print("vhhhat?");

这将会提示我无法在非静态上下文中访问静态方法,但Test和main是静态的,它指的是什么?

1
请参考XmlReader.Create,这是一个非静态类中静态方法的示例。 - Pavel Minaev
11
问题在于名称不够准确。一个“静态方法”应该被称为类似于VB中的“共享方法”。一个类是对象构建的蓝图,但是静态类不能被构建,因此它们不应该被称为类。同样,VB是正确的,将它们称为“模块”。当名称具有描述性时,回答问题更容易。你的问题是:为什么会有一个在类中而不在模块中的“共享方法”?答案是:为了在其类的实例之间共享它。 - Eric Lippert
7个回答

30

静态类意味着你不能在非静态环境中使用它,也就是说你不能实例化该类并调用其中的方法。如果你想使用你的打印方法,你需要这样做:

myOtherClass.print("vhhhat?");

这并不是静态的,因为你创建了一个名为moc的类实例:

myOtherClass moc = new myOtherClass();

24

首先,是错误信息:

moc.print("vhhhat?");

尝试在类的实例(即非静态上下文)上调用静态方法。要正确调用print(),您应该执行以下操作:

myOtherClass.print("vhhhat?");

针对第一个问题,非静态类中存在静态方法有很多原因。基本上,如果有一个与该类关联的操作,但不与任何特定的类实例相关,则它应该是一个静态方法。例如,String.Format()(或任何String静态方法)不应在字符串实例上操作,而应该与String类相关联。因此它们是静态的。


1
使用String.Format()的优秀示例 - webworm

14
这意味着您正在使用实例(moc)来引用一个静态方法(myOtherClass.print),从而导致静态上下文中无法访问静态方法的错误。您需要重新组织代码,使其如下所示:
myOtherClass.print("vhhhat?");

这将会被正确编译。

静态方法是在类本身上工作,而不是在类的特定实例上工作的方法。 这有很多用途 - 其中一个例子是用于实现工厂模式


4

正确的程序应该是:

class myClass
{
    public void print(string mess)
    {
        Console.WriteLine(mess);
    }
}

class myOtherClass
{
    public static void print(string mess)
    {
        Console.WriteLine(mess);
    }
    public void printMe(string mess)
    {
        Console.WriteLine(mess);
    }
}

public static class Test
{
    public static void Main()
    {
        myClass mc = new myClass();
        mc.print("hello");

        myOtherClass moc = new myOtherClass();
        myOtherClass.print("vhhhat?");
        moc.printMe("test me");


    }
}

4
有时函数的“目标”与对象(类的实例)无关,而是特定于类本身。
例如,一个工厂方法:
SomeClass obj = SomeClass.CreateInstance();

当语言具有允许对类进行操作的元编程功能时,这一点更加明显。在Python中,通过约定,这种区分更加明确:传递给函数的第一个参数被命名为"cls"或"self"之类的东西,并指示该函数可能对类(当它是"类方法"时)或实例(当它是实例方法时,您更习惯的类型)进行操作。


0
当您在一个对象实例上调用方法时,您是在非静态上下文中调用它。在哪个方法中执行此操作并不重要。

0
这是一个很好的例子,说明在非静态类中使用静态方法的情况:
ASP.NET AJAX回调到ASPX页面中的Web方法

链接无法使用。 - Thomas Adrian

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