【问题标题】:Why does C# not allow variables to be declared static in methods?为什么 C# 不允许变量在方法中声明为静态的?
【发布时间】:2011-09-08 23:40:56
【问题描述】:

我正在阅读 Microsoft 的一些 AppHub 示例,这是其中一个功能的开始:

if (string.IsNullOrEmpty(textureFilename))
{
    string message = "textureFilename wasn't set properly, so the " +
        "particle system doesn't know what texture to load. Make " +
        "sure your particle system's InitializeConstants function " +
        "properly sets textureFilename.";
    throw new InvalidOperationException(message);
}

ReSharper 说要使这个值成为常数,而不是每次都重新声明它。但是,此字符串值仅在此函数中使用,因此不必将其设为成员变量。理想情况下,变量的范围应该限制在这个函数中。对吧?

另外,我同意“将字符串放在资源文件中”的说法。在这种情况下,这很可能是最佳解决方案。它不仅解决了本地化问题,而且还避免了每次函数调用都重新初始化变量,并且不再弄乱源文件。然而,这只是一个例子。

我知道很多人可能会说“过早的优化是万恶之源”,但请注意这只是一个例子。如果这个准常数变量很复杂并且每次调用都重新初始化它会导致明显的减速怎么办?

Visual Basic .NET 允许程序员将函数中的变量声明为静态变量。例如,在这段代码中TestFunction只会在我第一次点击按钮时被调用:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Static example As Integer = TestFunction()

    MessageBox.Show(example)
End Sub

Private Function TestFunction() As Integer
    Console.WriteLine("Method Accessed")

    Return 5
End Function

据我所知,C# 不允许这样做。有什么特别的原因吗?在这种情况下,它似乎是完美的。它将变量范围限制为函数,并且只在第一次初始化它。即使对象创建成本很高,也只会执行一次。那么为什么这不可用呢?还是这样?

感谢阅读!

【问题讨论】:

  • 我不知道为什么它不可用。 (可能是因为 VB.NET 是一种稍微好一点的语言 :])不过,让它成为一个成员变量也不错 - 虽然在范围方面有点问题,但单类文件应该由同一个人编写,并且变量的用途应该很明显。
  • VB 中的静态“本地”只是一个编译器技巧。生成的 IL 与您使用类级静态字段(除了编译器生成的名称)没有什么不同。

标签: c# coding-style static scope standards


【解决方案1】:

ReSharper 说要使这个值成为常数,而不是重新声明 每次都这样。但是,此字符串值仅用于此 函数,因此不需要将其设为成员变量。 理想情况下,变量的范围应该限制在这个函数中。 对吧?

是的,但是 resharper 会将局部变量设为 const,而不是创建成员字段

if (string.IsNullOrEmpty(textureFilename))
{
    const string message = "textureFilename wasn't set properly, so the " +
        "particle system doesn't know what texture to load. Make " +
        "sure your particle system's InitializeConstants function " +
        "properly sets textureFilename.";
    throw new InvalidOperationException(message);
}

【讨论】:

  • 嘿,我脸上的鸡蛋。我不知道您可以在方法中使用常量变量。在方法中的静态变量不起作用后,我什至没有尝试静态。另外,我想我假设如果有可能微软会在他们的代码中做到这一点。哦,好的,谢谢!
  • @Kyle:你当然不能有“常量变量”,因为“常量”和“变量”是相反的。 (您可以拥有局部常量,但它们不是“常量变量”。)在 C# 中没有办法拥有局部范围的静态字段。如果你想要一个静态字段,然后创建一个私有类范围的静态字段。
【解决方案2】:

您有什么理由不想像 ReSharper 建议的那样将其设为本地 const

if (string.IsNullOrEmpty(textureFilename))
{
    const string message = "...";
    throw new InvalidOperationException(message);
}

【讨论】:

  • O_O 没想到你能做到这一点。老实说,我什至没有费心对其进行重新锐化,因为我认为它只是将它作为一个常量成员变量放在类中。
【解决方案3】:

有一个blog post in the C# FAQ about this exact question

实际上,有两个原因。首先,在几乎所有情况下,您都可以通过const 或成员级别的静态变量来完成同样的事情。其次,其他语言(如 C 和 C++)中的局部静态变量在多线程场景中经常会出现问题。

此外,我很高兴这被遗漏了。状态,作为数据,就像它在 C# 中的方式一样,只与类型或实例相关联。这将是第三种存储状态的方式,并增加了混乱。

至于为什么 VB.Net 包含这个 - 包含这个是为了向后兼容 VB。话虽如此,编译器实际上将其转换为该类型的静态成员,因此它与 C# 的支持级别确实相同。

【讨论】:

    猜你喜欢
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-10
    • 1970-01-01
    • 2013-03-13
    • 2011-10-21
    • 2016-10-06
    相关资源
    最近更新 更多