C#: 静态方法中的静态变量

52

在静态方法中可以有静态变量吗?这个变量的值是否会在该方法的所有调用中保留?

例如:

public static void MyMethod()
{
    static int x = 0;
    x++;
}

你是因为之前在VB.NET中使用过Shared局部变量而问这个问题吗?无论如何,CLR本身并不支持这种功能,因此VB.NET必须使用一些幕后技巧来创建这种效果。 - Cody Gray
2
你需要的是一个静态类成员。 - David Heffernan
1
@Colin - 我认为他想让x只能被MyMethod()访问,而不管它们是否在这个类中的其他方法。 - blizpasta
可能是Does C# support the use of static local variables?的重复问题。 - nawfal
有人知道这在7年内是否有所改变。我模糊地记得这可能是一个新功能。 - RLH
3个回答

52

不行,您无法拥有本地静态变量。

根据MSDN的描述:

C#不支持局部静态变量(在方法作用域中声明的变量)。

还可以在此处看到:

static修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或其他类型(除了类)。

正如您所见,局部变量并没有被提及。


然而,您可以使用静态字段:

public class MyClass
{
    private static int MyVariable = 10;

    public static void MyMethod()
    {
        MyVariable++;
    }
}

43
很不幸,如果MyVariable仅在MyMethod中使用,那么它应该放在MyMethod中,而不是暴露给类的其余部分。 - AustinWBryan
4
这可能是使用C#而不是旧的“C”语言的唯一缺点。C++作用域较弱,但您可以拥有本地静态变量。这就是使strtok函数成为可能的原因。从POSIX strtok页面:此函数使用静态存储来在调用之间跟踪当前字符串位置。我在C++中编写了一个变体,它忽略了空记录并接受任何可以由C++ String类表示的分隔符。了解这些东西的工作原理应该使其能够在任何语言中复制,但遗憾的是,这是C#的一个弱点。 - Joel Trauger
4
C++的作用域规则比C#弱在哪里?就我所知,它们是相同的,除了C++可能有本地静态变量。 - Clearer
如果我没记错,在C++中,你必须显式调用继承来获得类的属性。任何没有通过继承明确传递的内容都会自动变成私有的。在C#中,只需将类设为public,就可以自动继承该类的所有公共成员。C#还允许使用内部作用域来进一步控制类成员的作用域。因此,我认为C++的作用域较弱,尽管其他人可能认为它更强大...因为C#中不存在静态变量。 - Joel Trauger

11

不可以,但你可以有:

private static int x = 0;
public static void MyMethod()
{
     x++;
} 

我想如果你这样做的话,你大多会想使用[ThreadStatic]private static int x = 0;吧? - Chris F Carroll
问题在于,在这种情况下,你可能不希望其他类的其他部分直接访问x。我相信答案是“那就把所有东西都包装在一个静态类中”,但这似乎需要很多样板代码。 - matt

0

这里有一种巧妙的方法可以实现你想要做的事情。将MyMethod转换为一个创建在x上的闭包的Action。变量x只会对最内层的委托可见,并且表现得像静态变量。如果有人有改进这个模式的建议,请告诉我。

public static readonly Action MyMethod = new Func<Action>(delegate ()
{
    var x = 0;
    return delegate () { x++; };
}).Invoke();

//example usage:
public void Init() {
    MyMethod();
}

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