【问题标题】:Is there reason why you can't declare a static variable within a C# method?为什么不能在 C# 方法中声明静态变量?
【发布时间】:2013-08-01 09:26:34
【问题描述】:

在过去的几年里,我一直在使用 C 语言,我已经习惯了将单一用途的 static 变量放在我的代码中使用它们的位置附近。

在编写一个需要方法范围静态值的非常基本的方法时,我有点惊讶地发现编译器不喜欢我试图从我的方法中定义一个静态对象。

谷歌搜索已证实这在 C# 中是不可能的。不过,我很好奇为什么代码(如下所示)完全不受限制。

public int incrementCounterAndReturn()
{
    static int i = 0;
    return ++i;
}

当然,这是一个简单的示例,可以针对相同的效果重新定义,但这不是重点。方法范围,静态值有它​​们的位置和目的。哪些设计决策阻止了在 C# 中实现这样的静态对象?

我们使用的是 C# 版本 5.0,现在是 2013 年。我只能假设这是不可能的,因为设计选择,而不仅仅是因为“实现起来既复杂又难”。有人知道内幕消息吗?

【问题讨论】:

  • 我不知道他们没有在 C# 中实现这一点的任何陈述原因。我个人认为这是不好的做法,至少对于我正在考虑的用例而言。
  • 只需在 VB.NET 中编写此代码。并查看生成的 IL。是的,当多个线程可以调用此方法时,确保变量只初始化一次是的代价。隐藏大量代码不是 C# 方式。也不是 VB.NET 方式,但他们别无选择。而不是 C 方式,它只是让你把腿打断。
  • 感谢@HansPassant。我应该考虑到这一点!
  • 一个相关的、更受欢迎的功能请求:Property backing value scope.

标签: c# static compiler-errors


【解决方案1】:

语言设计团队无需提供不实施某项功能的理由。相反,需要该功能的人需要证明该功能是设计、实施、测试和教育团队花费预算的最佳方式。没有人成功地为您提出的功能做到这一点。

如果我还在设计团队中并且提出了这个功能,我会指出这完全没有必要。 C 中的特性是开发人员混淆的一个已知原因,特别是对于新手来说,本地与类型范围的好处是微乎其微的。

【讨论】:

  • 谢谢埃里克!你是对的,没有必要说明为什么你没有将某些东西实现为一种语言。尽管如此,我还是很好奇这是否被决定为一个特定的选择作为避免做的事情,或者是否因为这将是大量的工作而没有做的事情,几乎没有(甚至没有)好处。再次,谢谢。这就是我一直在寻找的。​​span>
  • 我添加了一些文字来解决您的评论。
【解决方案2】:

底层运行时不提供方法级别的静态变量。在 CLR 中,所有“静态”数据都是在类型级别而不是方法级别定义的。 C# 决定不在其语言设计的语言级别添加它。

这纯粹是一种设计选择。 VB.Net 编译为相同的 IL,通过 the Shared keyword in a Function or Sub statement 确实允许这样做(尽管它是通过编译器将变量“提升”为类级静态变量来处理的)。

【讨论】:

  • 我主要是 c#,但对 VB 如何处理这个问题感到好奇。如果你在不同的方法中用相同的名称声明两个静态方法级变量,VB 编译器会做什么?给他们起别名?您必须使用TypeName.Alias 访问它们吗?还是只能从方法中访问它们?
  • @CharlesBretana 它会破坏变量的名称,类似于 C# 中自动属性的后备存储所发生的情况。 “真实”名称(就 CLR 而言)不是用户输入的内容。
  • 我忘记了 Shared 关键字(我已经很久没有编写任何形式的 VB 了。)我了解静态在 C# 中的工作原理。不过,如果你想实现这一点,我认为它是可以做到的。我不认为这很容易,但正如我所说,我认为在 .Net 的 10 多年中,它应该不会那么困难,它从未被添加为功能。我想没有足够的干草叉......
  • @RLH 如果语言团队认为有必要,可以轻松添加它。它很容易解决(通过自己在班级级别声明),所以这样做几乎/没有意义。
  • @RLH 在此处查看 Eric Lippert 的答案:stackoverflow.com/a/2806990/65358 这与“为什么不这样做”有关(对于任何 C# 功能)
【解决方案3】:

因为在 CLR 中,静态变量与 TYPE 相关联。它们的存储与它们关联的类型(类或结构)相关联。

【讨论】:

  • 虽然这是事实,但如果设计人员决定这样做,该语言可以轻松解决它。例如,VB 就可以。
【解决方案4】:

static 变量的作用域是类,而不是对象实例。为了使这个工作,你的方法必须声明static,我相信你的类也必须是static(因为实例化不相关)。

但变量本身必须在类级别声明。 C# 不允许您创建方法局部静态变量。

值得注意的是:这些类型的操作使得正确地对方法进行单元测试变得非常困难。通常在 C# 中,人们会创建一个普通的类来保持这种状态;事实上,that's exactly how yield return works 在幕后。

【讨论】:

  • 我现在不在我的代码前面,但你是说如果我将一个方法定义为static,我也可以在该方法内定义一个static int?很有趣。
  • @RLH 不,你不能 - 你仍然需要使静态变量类级别。
  • @RLH:不,我错了;我刚试了一下,IDE 不接受。 static 变量声明必须在类级别完成。
【解决方案5】:

.NET 框架和语言的设计理念是,任何将要编译程序集的人都应该被认为是值得信赖的,可以访问其中的所有代码。从语义的角度来看,在方法 bar 内声明一个静态变量 foo 将等同于在方法外声明一个私有静态变量并在方法内访问它,只要选择的名称不是' t在其他任何地方使用。如果按照惯例结合方法名称和含义(例如bar_foo),通常可以很容易地避免命名冲突。由于语义等价于在方法外声明变量,因此无需在方法内声明。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-06
    • 2012-03-05
    • 2010-09-24
    • 2010-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多